/*	Copyright (c) 1984, 1986, 1987, 1988 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident	"@(#)libm:i386/log.c	1.2"
#ident	"@(#)log.c	2.2 - 87/04/20"

/*LINTLIBRARY*/

/*
 *	log returns the natural logarithm of its double-precision argument.
 *	log10 returns the base-10 logarithm of its double-precision argument.
 *	Returns EDOM error and value -HUGE if argument <= 0.
 *	Algorithm and coefficients from Cody and Waite (1980).
 *	Calls frexp.
 */

#include <math.h>
#include <errno.h>

extern double log_error();

asm	double xlog(x)
{
%mem	x;
	fldln2				/ load log(e)2
	fldl	x
	fyl2x
}

asm	double xlog10(x)
{
%mem	x;
	fldlg2				/ load log(10)2
	fldl	x
	fyl2x
}

double
log(x)
double x;
{
	if (x <= 0)
		return (log_error(x, "log", 3));

	return(xlog(x));
}

double
log10(x)
double x;
{
	if (x <= 0)
		return (log_error(x, "log10", 5));

	return(xlog10(x));
}

static double
log_error(x, f_name, name_len)
double x;
char *f_name;
unsigned int name_len;
{
	char *err_type;
	unsigned int mess_len;
	struct exception exc;

	exc.name = f_name;
	exc.retval = -HUGE;
	exc.arg1 = x;
	if (x) {
		exc.type = DOMAIN;
		err_type = ": DOMAIN error\n";
		mess_len = 15;
	} else {
		exc.type = SING;
		err_type = ": SING error\n";
		mess_len = 13;
	}
	if (!matherr(&exc)) {
		(void) write(2, f_name, name_len);
		(void) write(2, err_type, mess_len);
		errno = EDOM;
	}
	return (exc.retval);
}
