ifqlgama.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 228 行

C
228
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


//
// IFQLGAMA     : log of gamma function for extended PRECISION argument
//

#include "fmath.h"
#include <float.h>

#include "ftnstd.h"
#include "ifenv.h"

static  const extended __FAR  p1[9] = {  6.304933722864032e02,
                           1.389482659233250e02,
                          -2.331861065739548e03,
                          -2.651470392943388e03,
                          -8.953073589022869e02,
                          -9.229503102917111e01,
                          -1.940352203312667e00,
                           4.368019694395194e00,
                           1.279153645893113e02 };
static  const extended __FAR  p2[9] = {  1.071722590306920e04,
                           6.527047912184606e04,
                           1.176398389569621e05,
                          -9.726314581896472e03,
                          -1.266094622188023e05,
                          -5.393468741199669e04,
                          -3.895916159676326e03,
                           5.397392180667399e00,
                           5.334390026324024e02 };
static  const extended __FAR  p3[9] = { -6.114039864945718e07,
                          -5.588132821261888e08,
                          -9.078970022444525e08,
                           3.662935130796460e09,
                           4.658700336821218e09,
                          -4.570725249206307e09,
                          -2.220833171087439e09,
                          -1.474322990113017e04,
                          -1.959850795570400e06 };
static  const extended __FAR  p4[7] = {  8.40596949829e-04,
                          -5.9523334141881e-04,
                           7.9365078409227e-04,
                          -2.777777777769526e-03,
                           8.333333333333333e-02,
                           9.189385332046727e-01,
                          -1.7816839846e-03 };
static  const extended __FAR  q1[8] = { 6.689575153359349e02,
                          2.419887329355996e03,
                          3.354196974608081e03,
                          1.860416170944268e03,
                          3.944307810159532e02,
                          2.682132440551618e01,
                          3.440812622259858e-01,
                          5.948212550303777e01 };
static  const extended __FAR  q2[8] = { 5.314589562326176e03,
                          5.493654949398033e04,
                          2.205757574602192e05,
                          3.602313576600391e05,
                          2.273446951911101e05,
                          4.560612434396495e04,
                          1.702062439974796e03,
                          1.670328399370593e02 };
static  const extended __FAR  q3[8] = { -5.636057205056241e05,
                          -2.691827587118628e07,
                          -4.411606716771217e08,
                          -2.774890551941383e09,
                          -6.579874397740792e09,
                          -4.980644951174248e09,
                          -6.677373781427094e08,
                          -2.722530175870899e03 };
static  const extended __FAR  xinf  = { LDBL_MAX };
static  const extended __FAR  pi    = { 3.141592653589793e0 };
static  const extended __FAR  eps   = { LDBL_EPSILON };
static  const extended __FAR  big   = { 1.28118e305 };

extern  extended          QINT(extended);
extern  extended          QMOD(extended,extended);


extended  __lgamma( extended arg, const extended __FAR *my_inf ) {
//================================================================

    bool        mflag;
    int         j;
    extended      sign;
    extended      y;
    extended      t;
    extended      r;
    extended      top;
    extended      den;
    extended      a;
    extended      b;

    mflag = FALSE;
    t = arg;
    if( t < 0.0 ) { // argument is negative
        mflag = TRUE;
        t = -t;
        r = QINT( t );
        sign = 1.0;
        if( QMOD( t, 2.0 ) == 0.0 ) {
            sign = -1.0;
        }
        r = t - r;
        if( r == 0.0 ) {
            return( *my_inf );
        }
        // argument is not a negative integer
        r = pi / sin( r * pi ) * sign;
        t = t + 1.0;
        r = log( fabs( r ) );
    }
    // evaluate approximation for ln(gamma(t)), t > 0.0
    if( t > 12.0 ) {
        top = log( t );
        top = t * ( top - 1.0 ) - .5 * top;
        t = 1.0 / t;
        y = top;
        if( t >= eps ) {
            b = t * t;
            a = p4[6];
            for( j = 0; j <= 4; ++j ) {
                a = a * b + p4[j];
            }
            y = a * t + p4[5] + top;
        }
        if( mflag ) {
            y = r - y;
        }
        return( y );
    } else if( t > 4.0 ) {
        top = p3[7] * t + p3[8];
        den = t + q3[7];
        for( j = 0; j <= 6; ++j ) {
            top = top * t + p3[j];
            den = den * t + q3[j];
        }
        y = top / den;
        if( mflag ) {
            y = r - y;
        }
        return( y );
    } else if( t >= 1.5e0 ) {
        b = t - 1.0;
        top = p2[7] * t + p2[8];
        den = t + q2[7];
        a = b - 1.0;
        for( j = 0; j <= 6; ++j ) {
            top = top * t + p2[j];
            den = den * t + q2[j];
        }
        y = ( top / den ) * a;
        if( mflag ) {
            y = r - y;
        }
        return( y );
    } else {
        if( t >= .5 ) {
            top = t - .5;
            b = 0.0;
            a = top - .5;
        } else {
            b = -log( t );
            a = t;
            t = t + 1.0;
            if( a < eps ) {
                return( b );
            }
        }
        top = p1[7] * t + p1[8];
        den = t + q1[7];
        for( j = 0; j <= 6; ++j ) {
            top = top * t + p1[j];
            den = den * t + q1[j];
        }
        y = ( top / den ) * a + b;
        if( mflag ) {
            y = r - y;
        }
        return( y );
    }
}


extended  QLGAMA( extended arg ) {
//================================

    if( fabs( arg ) >= big ) return( xinf );
    if( arg == 0.0 ) return( xinf );
    return( __lgamma( arg, &xinf ) );
}

extended XQLGAMA( extended *arg ) {
//=================================

    return( QLGAMA( *arg ) );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?