1997-03-29 17:39  Ulrich Drepper  <drepper@cygnus.com>

	* math/Makefile (routines): Add carg, s_ccosh and s_csinh.

	* math/complex.h: Add C++ protection.

	* math/libm-test.c (cexp_test): Correct a few bugs.
	(csinh_test): New function.
	(ccosh_test): New function.
	(cacos_test): New function.
	(cacosh_test): New function.
	(casinh_test): New function.
	(catanh_test): New function.
	(main): Add calls to csinh_test and ccosh_test.

	* misc/Makefile (tests): Add tst-tsearch.
	Add rule to link tst-tsearch against libm.
	* misc/tsearch.c: Rewritten to use Red-Black-Tree algorithm by
	Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>.
	* misc/tst-tsearch.c: New file.

	* stdio-common/bug5.c: Clear LD_LIBRARY_PATH environment variable
	before using system.
	* stdio-common/test-popen.c: Clear LD_LIBRARY_PATH environment variable
	before using popen.

	* sysdeps/libm-ieee754/s_cexp.c: Correct handling of special cases.
	* sysdeps/libm-ieee754/s_cexpf.c: Likewise.
	* sysdeps/libm-ieee754/s_cexpl.c: Likewise.

	* sysdeps/libm-i387/s_cexp.S: New file.  ix87 specific implementation
	of complex exponential function.
	* sysdeps/libm-i387/s_cexpf.S: New file.
	* sysdeps/libm-i387/s_cexpl.S: New file.

	* sysdeps/libm-ieee754/s_ccosh.c: New file.  Implementation of
	complex cosh function.
	* sysdeps/libm-ieee754/s_ccoshf.c: New file.
	* sysdeps/libm-ieee754/s_ccoshl.c: New file.
	* sysdeps/libm-ieee754/s_csinh.c: New file.  Implementation of
	complex sinh function.
	* sysdeps/libm-ieee754/s_csinhf.c: New file.
	* sysdeps/libm-ieee754/s_csinhl.c: New file.

	* math/carg.c: New file.  Generic implementatio of carg function.
	* math/cargf.c: New file.
	* math/cargl.c: New file.

1997-03-29 16:07  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/posix/system.c: Update copyright.

1997-03-29 04:18  Ulrich Drepper  <drepper@cygnus.com>

	* elf/dl-error.c (_dl_catch_error): Add another argument which is
	passed to OPERATE.
	(_dl_receive_error): Likewise.
	* elf/link.h: Change prototypes for _dl_catch_error and
	_dl_receive_error to reflect above change.
	* elf/dl-deps.c: Don't use nested function.  Call _dl_catch_error
	with additional argument with pointer to data.
	* elf/dlclose.c: Likewise.
	* elf/dlerror.c: Likewise.
	* elf/dlopen.c: Likewise.
	* elf/dlsym.c: Likewise.
	* elf/dlvsym.c: Likewise.
	* elf/rtld.c: Likewise.
	* nss/nsswitch.c: Likewise.
	Patch by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>.

1997-03-28 21:14  Miguel de Icaza  <miguel@nuclecu.unam.mx>

	* elf/dl-error.c: Manually set up the values of "c", this avoids a
	call to memcpy and a zero 152 bytes structure.

	* sysdeps/sparc/dl-machine.h (elf_machine_rela): Test
	RTLD_BOOTSTRAP to avoid performing relative relocs on a second
	pass.

	* sysdeps/sparc/udiv_qrnnd.S: Make the code PIC aware.

	* sysdeps/unix/sysv/linux/sparc/Dist: Add kernel_stat.h and
	kernel_sigaction.h

	Add Linux/SPARC specific definitions.
	* sysdeps/unix/sysv/linux/sparc/fcntlbits.h: New file.
	* sysdeps/unix/sysv/linux/sparc/ioctls.h: New file.
	* sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h: New file.
	* sysdeps/unix/sysv/linux/sparc/kernel_stat.h: New file.
	* sysdeps/unix/sysv/linux/sparc/sigaction.h: New file.
	* sysdeps/unix/sysv/linux/sparc/signum.h: New file.
	* sysdeps/unix/sysv/linux/sparc/termbits.h: New file.

1997-03-28 13:06  Philip Blundell  <pjb27@cam.ac.uk>

	* sysdeps/posix/getaddrinfo.c (gaih_inet_serv): Use
	__getservbyname_r() not getservbyname().
	(BROKEN_LIKE_POSIX): Define to 1 so we get strict POSIX behaviour.
This commit is contained in:
Ulrich Drepper 1997-03-29 17:32:35 +00:00
parent e7fd8a39ab
commit 993b3242cd
48 changed files with 5270 additions and 771 deletions

View File

@ -1,3 +1,102 @@
1997-03-29 17:39 Ulrich Drepper <drepper@cygnus.com>
* math/Makefile (routines): Add carg, s_ccosh and s_csinh.
* math/complex.h: Add C++ protection.
* math/libm-test.c (cexp_test): Correct a few bugs.
(csinh_test): New function.
(ccosh_test): New function.
(cacos_test): New function.
(cacosh_test): New function.
(casinh_test): New function.
(catanh_test): New function.
(main): Add calls to csinh_test and ccosh_test.
* misc/Makefile (tests): Add tst-tsearch.
Add rule to link tst-tsearch against libm.
* misc/tsearch.c: Rewritten to use Red-Black-Tree algorithm by
Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>.
* misc/tst-tsearch.c: New file.
* stdio-common/bug5.c: Clear LD_LIBRARY_PATH environment variable
before using system.
* stdio-common/test-popen.c: Clear LD_LIBRARY_PATH environment variable
before using popen.
* sysdeps/libm-ieee754/s_cexp.c: Correct handling of special cases.
* sysdeps/libm-ieee754/s_cexpf.c: Likewise.
* sysdeps/libm-ieee754/s_cexpl.c: Likewise.
* sysdeps/libm-i387/s_cexp.S: New file. ix87 specific implementation
of complex exponential function.
* sysdeps/libm-i387/s_cexpf.S: New file.
* sysdeps/libm-i387/s_cexpl.S: New file.
* sysdeps/libm-ieee754/s_ccosh.c: New file. Implementation of
complex cosh function.
* sysdeps/libm-ieee754/s_ccoshf.c: New file.
* sysdeps/libm-ieee754/s_ccoshl.c: New file.
* sysdeps/libm-ieee754/s_csinh.c: New file. Implementation of
complex sinh function.
* sysdeps/libm-ieee754/s_csinhf.c: New file.
* sysdeps/libm-ieee754/s_csinhl.c: New file.
* math/carg.c: New file. Generic implementatio of carg function.
* math/cargf.c: New file.
* math/cargl.c: New file.
1997-03-29 16:07 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/posix/system.c: Update copyright.
1997-03-29 04:18 Ulrich Drepper <drepper@cygnus.com>
* elf/dl-error.c (_dl_catch_error): Add another argument which is
passed to OPERATE.
(_dl_receive_error): Likewise.
* elf/link.h: Change prototypes for _dl_catch_error and
_dl_receive_error to reflect above change.
* elf/dl-deps.c: Don't use nested function. Call _dl_catch_error
with additional argument with pointer to data.
* elf/dlclose.c: Likewise.
* elf/dlerror.c: Likewise.
* elf/dlopen.c: Likewise.
* elf/dlsym.c: Likewise.
* elf/dlvsym.c: Likewise.
* elf/rtld.c: Likewise.
* nss/nsswitch.c: Likewise.
Patch by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>.
1997-03-28 21:14 Miguel de Icaza <miguel@nuclecu.unam.mx>
* elf/dl-error.c: Manually set up the values of "c", this avoids a
call to memcpy and a zero 152 bytes structure.
* sysdeps/sparc/dl-machine.h (elf_machine_rela): Test
RTLD_BOOTSTRAP to avoid performing relative relocs on a second
pass.
* sysdeps/sparc/udiv_qrnnd.S: Make the code PIC aware.
* sysdeps/unix/sysv/linux/sparc/Dist: Add kernel_stat.h and
kernel_sigaction.h
Add Linux/SPARC specific definitions.
* sysdeps/unix/sysv/linux/sparc/fcntlbits.h: New file.
* sysdeps/unix/sysv/linux/sparc/ioctls.h: New file.
* sysdeps/unix/sysv/linux/sparc/kernel_sigaction.h: New file.
* sysdeps/unix/sysv/linux/sparc/kernel_stat.h: New file.
* sysdeps/unix/sysv/linux/sparc/sigaction.h: New file.
* sysdeps/unix/sysv/linux/sparc/signum.h: New file.
* sysdeps/unix/sysv/linux/sparc/termbits.h: New file.
1997-03-28 13:06 Philip Blundell <pjb27@cam.ac.uk>
* sysdeps/posix/getaddrinfo.c (gaih_inet_serv): Use
__getservbyname_r() not getservbyname().
(BROKEN_LIKE_POSIX): Define to 1 so we get strict POSIX behaviour.
1997-03-27 02:28 Ulrich Drepper <drepper@cygnus.com>
* gmon/gmon.c (monstartup): Mark all messages.

View File

@ -110,32 +110,26 @@ contact <bug-glibc@prep.ai.mit.edu>
**** Almost done!
[10] Write AVL-tree based tsearch() et.al. functions. Currently only
a very simple algorithm is used.
There is a public domain version but using this would cause problems
with the assignment.
[11] Extend regex and/or rx to work with wide characters and complete
[10] Extend regex and/or rx to work with wide characters and complete
implementation of character class and collation class handling.
It is planed to do a complete rewrite.
[12] Write access function for netmasks, bootparams, and automount
[11] Write access function for netmasks, bootparams, and automount
databases for nss_files and nss_db module.
The functions should be embedded in the nss scheme. This is not
hard and not all services must be supported at once.
[13] Rewrite utmp/wtmp functions to use database functions. This is much
[12] Rewrite utmp/wtmp functions to use database functions. This is much
better than the normal flat file format.
**** There are plans for a new approach to this problem. Please contact
bug-glibc@prep.ai.mit.edu before starting to work.)
[14] Several more or less small functions have to be written:
[13] Several more or less small functions have to be written:
+ tcgetid() and waitid() from XPG4.2
+ grantpt(), ptsname(), unlockpt() from XPG4.2
@ -145,7 +139,7 @@ contact <bug-glibc@prep.ai.mit.edu>
More information are available on request.
[15] We need to write a library for on-the-fly transformation of streams
[14] We need to write a library for on-the-fly transformation of streams
of text. In fact, this would be a recode-library (you know, GNU recode).
This is needed in several places in the GNU libc and I already have
rather concrete plans but so far no possibility to start this.

View File

@ -22,6 +22,29 @@
#include <dlfcn.h>
#include <stdlib.h>
struct openaux_args
{
/* The arguments to openaux. */
struct link_map *map;
int trace_mode;
const char *strtab;
ElfW(Dyn) *d;
/* The return value of openaux. */
struct link_map *aux;
};
static void
openaux (void *a)
{
struct openaux_args *args = (struct openaux_args *) a;
args->aux = _dl_map_object (args->map, args->strtab + args->d->d_un.d_val,
(args->map->l_type == lt_executable
? lt_library : args->map->l_type),
args->trace_mode);
}
void
_dl_map_object_deps (struct link_map *map,
struct link_map **preloads, unsigned int npreloads,
@ -75,27 +98,21 @@ _dl_map_object_deps (struct link_map *map,
/* There is at least one auxiliary library specified. We try to
load it, and if we can, use its symbols in preference to our
own. But if we can't load it, we just silently ignore it. */
const char *strtab
struct openaux_args args;
args.strtab
= ((void *) map->l_addr + map->l_info[DT_STRTAB]->d_un.d_ptr);
ElfW(Dyn) *d;
args.map = map;
args.trace_mode = trace_mode;
for (d = map->l_ld; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_AUXILIARY)
for (args.d = map->l_ld; args.d->d_tag != DT_NULL; ++args.d)
if (args.d->d_tag == DT_AUXILIARY)
{
struct link_map *aux;
void openaux (void)
{
aux = _dl_map_object (map, strtab + d->d_un.d_val,
(map->l_type == lt_executable
? lt_library : map->l_type),
trace_mode);
}
char *errstring;
const char *objname;
if (! _dl_catch_error (&errstring, &objname, openaux))
if (! _dl_catch_error (&errstring, &objname, openaux, &args))
/* The auxiliary object is actually there. Use it as
the first search element, even before MAP itself. */
preload (aux);
preload (args.aux);
}
}

View File

@ -85,19 +85,25 @@ _dl_signal_error (int errcode,
int
_dl_catch_error (char **errstring,
const char **objname,
void (*operate) (void))
void (*operate) (void *),
void *args)
{
int errcode;
struct catch *old, c = { errstring: NULL, objname: NULL };
/* We need not handle `receiver' since setting a `catch' is handle
struct catch *old, c;
/* We need not handle `receiver' since setting a `catch' is handled
before it. */
/* Some systems (.e.g, SPARC) handle constructors to local variables
inefficient. So we initialize `c' by hand. */
c.errstring = NULL;
c.objname = NULL;
old = catch;
errcode = setjmp (c.env);
if (errcode == 0)
{
catch = &c;
(*operate) ();
(*operate) (args);
catch = old;
*errstring = NULL;
*objname = NULL;
@ -112,7 +118,7 @@ _dl_catch_error (char **errstring,
}
void
_dl_receive_error (receiver_fct fct, void (*operate) (void))
_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
{
struct catch *old_catch;
receiver_fct old_receiver;
@ -124,7 +130,7 @@ _dl_receive_error (receiver_fct fct, void (*operate) (void))
catch = NULL;
receiver = fct;
(*operate) ();
(*operate) (args);
catch = old_catch;
receiver = old_receiver;

View File

@ -20,13 +20,14 @@
#include <link.h>
#include <dlfcn.h>
static void
dlclose_doit (void *handle)
{
_dl_close (handle);
}
int
dlclose (void *handle)
{
void doit (void)
{
_dl_close (handle);
}
return _dlerror_run (doit) ? -1 : 0;
return _dlerror_run (dlclose_doit, handle) ? -1 : 0;
}

View File

@ -64,7 +64,7 @@ dlerror (void)
}
int
_dlerror_run (void (*operate) (void))
_dlerror_run (void (*operate) (void *), void *args)
{
if (last_errstring != NULL)
/* Free the error string from the last failed command. This can
@ -72,6 +72,6 @@ _dlerror_run (void (*operate) (void))
free (last_errstring);
last_errcode = _dl_catch_error (&last_errstring, &last_object_name,
operate);
operate, args);
return last_errstring != NULL;
}

View File

@ -21,15 +21,31 @@
#include <link.h>
#include <dlfcn.h>
struct dlopen_args
{
/* The arguments for dlopen_doit. */
const char *file;
int mode;
/* The return value of dlopen_doit. */
struct link_map *new;
};
static void
dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;
args->new = _dl_open (args->file ?: "", args->mode);
}
void *
dlopen (const char *file, int mode)
{
struct link_map *new;
struct dlopen_args args;
args.file = file;
args.mode = mode;
void doit (void)
{
new = _dl_open (file ?: "", mode);
}
return _dlerror_run (doit) ? NULL : new;
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
}

View File

@ -22,47 +22,71 @@
#include <dlfcn.h>
#include <setjmp.h>
struct dlsym_args
{
/* The arguments to dlsym_doit. */
void *handle;
const char *name;
struct r_found_version version;
ElfW(Addr) caller;
/* The return values of dlsym_doit. */
ElfW(Addr) loadbase;
const ElfW(Sym) *ref;
};
static void
dlsym_doit (void *a)
{
struct dlsym_args *args = (struct dlsym_args *) a;
args->ref = NULL;
if (args->handle == NULL)
/* Search the global scope. */
args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
&(_dl_global_scope
?: _dl_default_scope)[2],
NULL, 0);
else if (args->handle == RTLD_NEXT)
{
struct link_map *l, *match;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (args->caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
args->loadbase = _dl_lookup_symbol_skip (args->name, &args->ref,
&_dl_loaded, NULL, l);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = args->handle;
struct link_map *mapscope[2] = { map, NULL };
args->loadbase = _dl_lookup_symbol (args->name, &args->ref, mapscope,
map->l_name, 0);
}
}
void *
dlsym (void *handle, const char *name)
{
ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0);
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
void doit (void)
{
if (handle == NULL)
/* Search the global scope. */
loadbase = _dl_lookup_symbol
(name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL, 0);
else if (handle == RTLD_NEXT)
{
struct link_map *l, *match;
struct dlsym_args args;
args.caller = (ElfW(Addr)) __builtin_return_address (0);
args.handle = handle;
args.name = name;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
loadbase = _dl_lookup_symbol_skip (name, &ref, &_dl_loaded, NULL, l);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
struct link_map *mapscope[2] = { map, NULL };
loadbase = _dl_lookup_symbol (name, &ref, mapscope, map->l_name, 0);
}
}
return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
return (_dlerror_run (dlsym_doit, &args)
? NULL : (void *) (args.loadbase + args.ref->st_value));
}

View File

@ -24,57 +24,82 @@
#include <dl-hash.h>
struct dlvsym_args
{
/* The arguments to dlvsym_doit. */
void *handle;
const char *name;
struct r_found_version version;
ElfW(Addr) caller;
/* The return values of dlvsym_doit. */
ElfW(Addr) loadbase;
const ElfW(Sym) *ref;
};
static void
dlvsym_doit (void *a)
{
struct dlvsym_args *args = (struct dlvsym_args *)a;
args->ref = NULL;
if (args->handle == NULL)
/* Search the global scope. */
args->loadbase = _dl_lookup_versioned_symbol (args->name, &args->ref,
&(_dl_global_scope
?: _dl_default_scope)[2],
NULL, &args->version, 0);
else if (args->handle == RTLD_NEXT)
{
struct link_map *l, *match;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (args->caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
args->loadbase = _dl_lookup_versioned_symbol_skip (args->name,
&args->ref,
&_dl_loaded,
NULL, &args->version,
l);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = args->handle;
struct link_map *mapscope[2] = { map, NULL };
args->loadbase = _dl_lookup_versioned_symbol (args->name, &args->ref,
mapscope, map->l_name,
&args->version, 0);
}
}
void *
__dlvsym (void *handle, const char *name, const char *version_str)
{
ElfW(Addr) caller = (ElfW(Addr)) __builtin_return_address (0);
ElfW(Addr) loadbase;
struct r_found_version version;
const ElfW(Sym) *ref = NULL;
void doit (void)
{
if (handle == NULL)
/* Search the global scope. */
loadbase = _dl_lookup_versioned_symbol
(name, &ref, &(_dl_global_scope ?: _dl_default_scope)[2], NULL,
&version, 0);
else if (handle == RTLD_NEXT)
{
struct link_map *l, *match;
struct dlvsym_args args;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
loadbase = _dl_lookup_versioned_symbol_skip
(name, &ref, &_dl_loaded, NULL, &version, l);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
struct link_map *mapscope[2] = { map, NULL };
loadbase = _dl_lookup_versioned_symbol
(name, &ref, mapscope, map->l_name, &version, 0);
}
}
args.handle = handle;
args.name = name;
args.caller = (ElfW(Addr)) __builtin_return_address (0);
/* Compute hash value to the version string. */
version.name = version_str;
version.hash = _dl_elf_hash (version_str);
args.version.name = version_str;
args.version.hash = _dl_elf_hash (version_str);
/* We don't have a specific file where the symbol can be found. */
version.filename = NULL;
args.version.filename = NULL;
return _dlerror_run (doit) ? NULL : (void *) (loadbase + ref->st_value);
return (_dlerror_run (dlvsym_doit, &args)
? NULL : (void *) (args.loadbase + args.ref->st_value));
}
weak_alias (__dlvsym, dlvsym)

View File

@ -238,21 +238,26 @@ extern void _dl_signal_error (int errcode,
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING and
*OBJECT are set to the strings passed to _dl_signal_error, and the error
code passed is the return value. ERRSTRING if nonzero points to a
malloc'ed string which the caller has to free after use. */
malloc'ed string which the caller has to free after use.
ARGS is passed as argument to OPERATE. */
extern int _dl_catch_error (char **errstring,
const char **object,
void (*operate) (void));
void (*operate) (void *),
void *args);
/* Call OPERATE, receiving errors from `dl_signal_error'. Unlike
`_dl_catch_error' the operation is resumed after the OPERATE
function returns. */
extern void _dl_receive_error (receiver_fct fct, void (*operate) (void));
function returns.
ARGS is passed as argument to OPERATE. */
extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
void *args);
/* Helper function for <dlfcn.h> functions. Runs the OPERATE function via
_dl_catch_error. Returns zero for success, nonzero for failure; and
arranges for `dlerror' to return the error details. */
extern int _dlerror_run (void (*operate) (void));
arranges for `dlerror' to return the error details.
ARGS is passed as argument to OPERATE. */
extern int _dlerror_run (void (*operate) (void *), void *args);
/* Open the shared object NAME and map in its segments.

View File

@ -140,6 +140,55 @@ _dl_start (void *arg)
void _start (void);
/* Some helper functions. */
/* Arguments to relocate_doit. */
struct relocate_args
{
struct link_map *l;
int lazy;
};
struct map_args
{
/* Argument to map_doit. */
char *str;
/* Return value of map_doit. */
struct link_map *main_map;
};
/* Arguments to version_check_doit. */
struct version_check_args
{
struct link_map *main_map;
int doexit;
};
static void
relocate_doit (void *a)
{
struct relocate_args *args = (struct relocate_args *) a;
_dl_relocate_object (args->l, _dl_object_relocation_scope (args->l),
args->lazy);
}
static void
map_doit (void *a)
{
struct map_args *args = (struct map_args *)a;
args->main_map = _dl_map_object (NULL, args->str, lt_library, 0);
}
static void
version_check_doit (void *a)
{
struct version_check_args *args = (struct version_check_args *)a;
if (_dl_check_all_versions (args->main_map, 1) && args->doexit)
/* We cannot start the application. Abort now. */
_exit (1);
}
unsigned int _dl_skip_args; /* Nonzero if we were run directly. */
static void
@ -234,14 +283,13 @@ of this helper program; chances are you did not intend to run this program.\n",
if (mode == verify)
{
void doit (void)
{
main_map = _dl_map_object (NULL, _dl_argv[0], lt_library, 0);
}
char *err_str = NULL;
const char *obj_name __attribute__ ((unused));
struct map_args args;
(void) _dl_catch_error (&err_str, &obj_name, doit);
args.str = _dl_argv[0];
(void) _dl_catch_error (&err_str, &obj_name, map_doit, &args);
main_map = args.main_map;
if (err_str != NULL)
{
free (err_str);
@ -469,14 +517,10 @@ of this helper program; chances are you did not intend to run this program.\n",
/* Now let us see whether all libraries are available in the
versions we need. */
{
void doit (void)
{
if (_dl_check_all_versions (main_map, 1) && mode == normal)
/* We cannot start the application. Abort now. */
_exit (1);
}
_dl_receive_error (print_missing_version, doit);
struct version_check_args args;
args.doexit = mode == normal;
args.main_map = main_map;
_dl_receive_error (print_missing_version, version_check_doit, &args);
}
if (mode != normal)
@ -535,11 +579,10 @@ of this helper program; chances are you did not intend to run this program.\n",
else if (lazy >= 0)
{
/* We have to do symbol dependency testing. */
struct relocate_args args;
struct link_map *l;
void doit (void)
{
_dl_relocate_object (l, _dl_object_relocation_scope (l), lazy);
}
args.lazy = lazy;
l = _dl_loaded;
while (l->l_next)
@ -548,7 +591,8 @@ of this helper program; chances are you did not intend to run this program.\n",
{
if (l != &_dl_rtld_map && l->l_opencount > 0)
{
_dl_receive_error (print_unresolved, doit);
args.l = l;
_dl_receive_error (print_unresolved, relocate_doit, &args);
*_dl_global_scope_end = NULL;
}
l = l->l_prev;

View File

@ -49,7 +49,7 @@ libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod \
w_log w_log10 w_pow w_remainder w_scalb w_sinh w_sqrt \
s_signbit s_fpclassify s_fmax s_fmin s_fdim s_nan s_trunc \
s_remquo s_log2 s_exp2 \
conj cimag creal cabs s_cexp
conj cimag creal cabs carg s_cexp s_csinh s_ccosh
libm-routines = $(libm-support) $(libm-calls) \
$(patsubst %_rf,%f_r,$(libm-calls:=f)) \
$(long-m-$(long-double-fcts))

29
math/carg.c Normal file
View File

@ -0,0 +1,29 @@
/* Compute argument of complex double value.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
double
__carg (__complex__ double x)
{
return __atan2 (__imag__ x, __real__ x);
}
weak_alias (__carg, carg)

29
math/cargf.c Normal file
View File

@ -0,0 +1,29 @@
/* Compute argument of complex float value.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
float
__cargf (__complex__ float x)
{
return __atan2f (__imag__ x, __real__ x);
}
weak_alias (__cargf, cargf)

29
math/cargl.c Normal file
View File

@ -0,0 +1,29 @@
/* Compute argument of complex long double value.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
long double
__cargl (__complex__ long double x)
{
return __atan2l (__imag__ x, __real__ x);
}
weak_alias (__cargl, cargl)

View File

@ -21,7 +21,11 @@
*/
#ifndef _COMPLEX_H
#define _COMPLEX_H 1
#include <features.h>
__BEGIN_DECLS
/* We might need to add support for more compilers here. But once ISO
C 9X is out hopefully all maintained compilers will provide the data
@ -41,7 +45,7 @@
#define I _Imaginary_I
/* Optimization aids. This is not yet implemented in gcc and yonce it
/* Optimization aids. This is not yet implemented in gcc and once it
is this will probably be available in a gcc header. */
#define CX_LIMITED_RANGE_ON
#define CX_LIMITED_RANGE_OFF
@ -99,4 +103,6 @@
#undef __MATHDECL
#undef __MATHCALL
__END_DECLS
#endif /* complex.h */

View File

@ -1550,7 +1550,7 @@ cexp_test (void)
check ("imag(cexp(+inf + 0i)) = 0", __imag__ result, 0);
result = FUNC(cexp) (BUILD_COMPLEX (plus_infty, minus_zero));
check_isinfp ("real(cexp(+inf - 0i)) = +inf", __real__ result);
check ("imag(cexp(+inf - 0i)) = 0", __imag__ result, 0);
check ("imag(cexp(+inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(cexp) (BUILD_COMPLEX (minus_infty, plus_zero));
check ("real(cexp(-inf + 0i)) = 0", __real__ result, 0);
@ -1574,11 +1574,11 @@ cexp_test (void)
check ("imag(cexp(-inf + 4.0i)) = -0", __imag__ result, minus_zero);
result = FUNC(cexp) (BUILD_COMPLEX (plus_infty, 2.0));
check_isinfn ("real(cexp(+inf + 2.0i)) = -0", __real__ result);
check_isinfp ("imag(cexp(+inf + 2.0i)) = 0", __imag__ result);
check_isinfn ("real(cexp(+inf + 2.0i)) = -inf", __real__ result);
check_isinfp ("imag(cexp(+inf + 2.0i)) = +inf", __imag__ result);
result = FUNC(cexp) (BUILD_COMPLEX (plus_infty, 4.0));
check_isinfn ("real(cexp(+inf + 4.0i)) = -0", __real__ result);
check_isinfn ("imag(cexp(+inf + 4.0i)) = -0", __imag__ result);
check_isinfn ("real(cexp(+inf + 4.0i)) = -inf", __real__ result);
check_isinfn ("imag(cexp(+inf + 4.0i)) = -inf", __imag__ result);
result = FUNC(cexp) (BUILD_COMPLEX (plus_infty, plus_infty));
check_isinfp ("real(cexp(+inf + i inf)) = +inf", __real__ result);
@ -1592,7 +1592,7 @@ cexp_test (void)
check ("imag(cexp(-inf + i inf)) = 0", __imag__ result, 0);
result = FUNC(cexp) (BUILD_COMPLEX (minus_infty, minus_infty));
check ("real(cexp(-inf - i inf)) = 0", __real__ result, 0);
check ("imag(cexp(-inf - i inf)) = 0", __imag__ result, 0);
check ("imag(cexp(-inf - i inf)) = -0", __imag__ result, minus_zero);
result = FUNC(cexp) (BUILD_COMPLEX (minus_infty, nan_value));
check ("real(cexp(-inf + i NaN)) = 0", __real__ result, 0);
@ -1621,6 +1621,760 @@ cexp_test (void)
}
static void
csinh_test (void)
{
__complex__ MATHTYPE result;
result = FUNC(csinh) (BUILD_COMPLEX (0.0, 0.0));
check ("real(csinh(0 + 0i)) = 0", __real__ result, 0);
check ("imag(csinh(0 + 0i)) = 0", __imag__ result, 0);
result = FUNC(csinh) (BUILD_COMPLEX (minus_zero, 0.0));
check ("real(csinh(-0 + 0i)) = -0", __real__ result, minus_zero);
check ("imag(csinh(-0 + 0i)) = 0", __imag__ result, 0);
result = FUNC(csinh) (BUILD_COMPLEX (0.0, minus_zero));
check ("real(csinh(0 - 0i)) = 0", __real__ result, 0);
check ("imag(csinh(0 - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(csinh) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(csinh(-0 - 0i)) = -0", __real__ result, minus_zero);
check ("imag(csinh(-0 - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(csinh) (BUILD_COMPLEX (0.0, plus_infty));
check ("real(csinh(0 + i Inf)) = 0", FUNC(fabs) (__real__ result), 0);
check_isnan ("imag(csinh(0 + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_zero, plus_infty));
check ("real(csinh(-0 + i Inf)) = -0", FUNC(fabs) (__real__ result), 0);
check_isnan ("imag(csinh(-0 + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (0.0, minus_infty));
check ("real(csinh(0 - i Inf)) = 0", FUNC(fabs) (__real__ result), 0);
check_isnan ("imag(csinh(0 - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_zero, minus_infty));
check ("real(csinh(-0 - i Inf)) = -0", FUNC(fabs) (__real__ result), 0);
check_isnan ("imag(csinh(-0 - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, 0.0));
check_isinfp ("real(csinh(+Inf + 0i)) = +Inf", __real__ result);
check ("imag(csinh(+Inf + 0i)) = 0", __imag__ result, 0);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, 0.0));
check_isinfn ("real(csinh(-Inf + 0i)) = -Inf", __real__ result);
check ("imag(csinh(-Inf + 0i)) = 0", __imag__ result, 0);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, minus_zero));
check_isinfp ("real(csinh(+Inf - 0i)) = +Inf", __real__ result);
check ("imag(csinh(+Inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, minus_zero));
check_isinfn ("real(csinh(-Inf - 0i)) = -Inf", __real__ result);
check ("imag(csinh(-Inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, plus_infty));
check_isinfp ("real(csinh(+Inf + i Inf)) = +-Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(csinh(+Inf + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, plus_infty));
check_isinfp ("real(csinh(-Inf + i Inf)) = +-Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(csinh(-Inf + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, minus_infty));
check_isinfp ("real(csinh(Inf - i Inf)) = +-Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(csinh(Inf - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, minus_infty));
check_isinfp ("real(csinh(-Inf - i Inf)) = -Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(csinh(-Inf - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, 4.625));
check_isinfn ("real(csinh(+Inf + i4.625)) = -Inf", __real__ result);
check_isinfn ("imag(csinh(+Inf + i4.625)) = -Inf", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, 4.625));
check_isinfp ("real(csinh(-Inf + i4.625)) = +Inf", __real__ result);
check_isinfn ("imag(csinh(-Inf + i4.625)) = -Inf", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, -4.625));
check_isinfn ("real(csinh(+Inf - i4.625)) = -Inf", __real__ result);
check_isinfp ("imag(csinh(+Inf - i4.625)) = +Inf", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, -4.625));
check_isinfp ("real(csinh(-Inf - i4.625)) = +Inf", __real__ result);
check_isinfp ("imag(csinh(-Inf - i4.625)) = +Inf", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (6.75, plus_infty));
check_isnan ("real(csinh(6.75 + i Inf)) = NaN", __real__ result);
check_isnan ("imag(csinh(6.75 + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (-6.75, plus_infty));
check_isnan ("real(csinh(-6.75 + i Inf)) = NaN", __real__ result);
check_isnan ("imag(csinh(-6.75 + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (6.75, minus_infty));
check_isnan ("real(csinh(6.75 - i Inf)) = NaN", __real__ result);
check_isnan ("imag(csinh(6.75 - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (-6.75, minus_infty));
check_isnan ("real(csinh(-6.75 - i Inf)) = NaN", __real__ result);
check_isnan ("imag(csinh(-6.75 - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (0.0, nan_value));
check ("real(csinh(0 + i NaN)) = 0", FUNC(fabs) (__real__ result), 0);
check_isnan ("imag(csinh(0 + i NaN)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_zero, nan_value));
check ("real(csinh(-0 + i NaN)) = -0", FUNC(fabs) (__real__ result), 0);
check_isnan ("imag(csinh(-0 + i NaN)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (plus_infty, nan_value));
check_isinfp ("real(csinh(+Inf + i NaN)) = +-Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(csinh(+Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (minus_infty, nan_value));
check_isinfp ("real(csinh(-Inf + i NaN)) = +-Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(csinh(-0 + i NaN)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (9.0, nan_value));
check_isnan ("real(csinh(9.0 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(csinh(9.0 + i NaN)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (-9.0, nan_value));
check_isnan ("real(csinh(-9.0 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(csinh(-9.0 + i NaN)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, 0.0));
check_isnan ("real(csinh(NaN + i0)) = NaN", __real__ result);
check ("imag(csinh(NaN + i0)) = NaN", __imag__ result, 0.0);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, minus_zero));
check_isnan ("real(csinh(NaN - i0)) = NaN", __real__ result);
check ("imag(csinh(NaN - i0)) = NaN", __imag__ result, minus_zero);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, 10.0));
check_isnan ("real(csinh(NaN + i10)) = NaN", __real__ result);
check_isnan ("imag(csinh(NaN + i10)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, -10.0));
check_isnan ("real(csinh(NaN - i10)) = NaN", __real__ result);
check_isnan ("imag(csinh(NaN - i10)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, plus_infty));
check_isnan ("real(csinh(NaN + i Inf)) = NaN", __real__ result);
check_isnan ("imag(csinh(NaN + i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, minus_infty));
check_isnan ("real(csinh(NaN - i Inf)) = NaN", __real__ result);
check_isnan ("imag(csinh(NaN - i Inf)) = NaN", __imag__ result);
result = FUNC(csinh) (BUILD_COMPLEX (nan_value, nan_value));
check_isnan ("real(csinh(NaN + i NaN)) = NaN", __real__ result);
check_isnan ("imag(csinh(NaN + i NaN)) = NaN", __imag__ result);
}
static void
ccosh_test (void)
{
__complex__ MATHTYPE result;
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, 0.0));
check ("real(ccosh(0 + 0i)) = 0", __real__ result, 1.0);
check ("imag(ccosh(0 + 0i)) = 0", __imag__ result, 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, 0.0));
check ("real(ccosh(-0 + 0i)) = -0", __real__ result, 1.0);
check ("imag(ccosh(-0 + 0i)) = 0", __imag__ result, 0);
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_zero));
check ("real(ccosh(0 - 0i)) = 0", __real__ result, 1.0);
check ("imag(ccosh(0 - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(ccosh(-0 - 0i)) = -0", __real__ result, 1.0);
check ("imag(ccosh(-0 - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, plus_infty));
check_isnan ("real(ccosh(0 + i Inf)) = NaN", __real__ result);
check ("imag(ccosh(0 + i Inf)) = +-0", FUNC(fabs) (__imag__ result), 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, plus_infty));
check_isnan ("real(ccosh(-0 + i Inf)) = NaN", __real__ result);
check ("imag(ccosh(-0 + i Inf)) = -0", FUNC(fabs) (__imag__ result), 0);
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_infty));
check_isnan ("real(ccosh(0 - i Inf)) = NaN", __real__ result);
check ("imag(ccosh(0 - i Inf)) = 0", FUNC(fabs) (__imag__ result), 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_infty));
check_isnan ("real(ccosh(-0 - i Inf)) = NaN", __real__ result);
check ("imag(ccosh(-0 - i Inf)) = -0", FUNC(fabs) (__imag__ result), 0);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, 0.0));
check_isinfp ("real(ccosh(+Inf + 0i)) = +Inf", __real__ result);
check ("imag(ccosh(+Inf + 0i)) = 0", __imag__ result, 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 0.0));
check_isinfp ("real(ccosh(-Inf + 0i)) = +Inf", __real__ result);
check ("imag(ccosh(-Inf + 0i)) = 0", __imag__ result, 0);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_zero));
check_isinfp ("real(ccosh(+Inf - 0i)) = +Inf", __real__ result);
check ("imag(ccosh(+Inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_zero));
check_isinfp ("real(ccosh(-Inf - 0i)) = +Inf", __real__ result);
check ("imag(ccosh(-Inf - 0i)) = -0", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, plus_infty));
check_isinfp ("real(ccosh(+Inf + i Inf)) = +Inf", __real__ result);
check_isnan ("imag(ccosh(+Inf + i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, plus_infty));
check_isinfp ("real(ccosh(-Inf + i Inf)) = +Inf", __real__ result);
check_isnan ("imag(ccosh(-Inf + i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_infty));
check_isinfp ("real(ccosh(Inf - i Inf)) = +Inf", __real__ result);
check_isnan ("imag(ccosh(Inf - i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_infty));
check_isinfp ("real(ccosh(-Inf - i Inf)) = +Inf", __real__ result);
check_isnan ("imag(ccosh(-Inf - i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, 4.625));
check_isinfn ("real(ccosh(+Inf + i4.625)) = -Inf", __real__ result);
check_isinfn ("imag(ccosh(+Inf + i4.625)) = -Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 4.625));
check_isinfn ("real(ccosh(-Inf + i4.625)) = -Inf", __real__ result);
check_isinfn ("imag(ccosh(-Inf + i4.625)) = -Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, -4.625));
check_isinfn ("real(ccosh(+Inf - i4.625)) = -Inf", __real__ result);
check_isinfp ("imag(ccosh(+Inf - i4.625)) = +Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, -4.625));
check_isinfn ("real(ccosh(-Inf - i4.625)) = -Inf", __real__ result);
check_isinfp ("imag(ccosh(-Inf - i4.625)) = +Inf", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (6.75, plus_infty));
check_isnan ("real(ccosh(6.75 + i Inf)) = NaN", __real__ result);
check_isnan ("imag(ccosh(6.75 + i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (-6.75, plus_infty));
check_isnan ("real(ccosh(-6.75 + i Inf)) = NaN", __real__ result);
check_isnan ("imag(ccosh(-6.75 + i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (6.75, minus_infty));
check_isnan ("real(ccosh(6.75 - i Inf)) = NaN", __real__ result);
check_isnan ("imag(ccosh(6.75 - i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (-6.75, minus_infty));
check_isnan ("real(ccosh(-6.75 - i Inf)) = NaN", __real__ result);
check_isnan ("imag(ccosh(-6.75 - i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (0.0, nan_value));
check_isnan ("real(ccosh(0 + i NaN)) = NaN", __real__ result);
check ("imag(ccosh(0 + i NaN)) = +-0", FUNC(fabs) (__imag__ result), 0);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_zero, nan_value));
check_isnan ("real(ccosh(-0 + i NaN)) = NaN", __real__ result);
check ("imag(ccosh(-0 + i NaN)) = +-0", FUNC(fabs) (__imag__ result), 0);
result = FUNC(ccosh) (BUILD_COMPLEX (plus_infty, nan_value));
check_isinfp ("real(ccosh(+Inf + i NaN)) = +Inf", __real__ result);
check_isnan ("imag(ccosh(+Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (minus_infty, nan_value));
check_isinfp ("real(ccosh(-Inf + i NaN)) = +Inf", __real__ result);
check_isnan ("imag(ccosh(-0 + i NaN)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (9.0, nan_value));
check_isnan ("real(ccosh(9.0 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(ccosh(9.0 + i NaN)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (-9.0, nan_value));
check_isnan ("real(ccosh(-9.0 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(ccosh(-9.0 + i NaN)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, 0.0));
check_isnan ("real(ccosh(NaN + i0)) = NaN", __real__ result);
check ("imag(ccosh(NaN + i0)) = NaN", __imag__ result, 0.0);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, minus_zero));
check_isnan ("real(ccosh(NaN - i0)) = NaN", __real__ result);
check ("imag(ccosh(NaN - i0)) = NaN", __imag__ result, minus_zero);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, 10.0));
check_isnan ("real(ccosh(NaN + i10)) = NaN", __real__ result);
check_isnan ("imag(ccosh(NaN + i10)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, -10.0));
check_isnan ("real(ccosh(NaN - i10)) = NaN", __real__ result);
check_isnan ("imag(ccosh(NaN - i10)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, plus_infty));
check_isnan ("real(ccosh(NaN + i Inf)) = NaN", __real__ result);
check_isnan ("imag(ccosh(NaN + i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, minus_infty));
check_isnan ("real(ccosh(NaN - i Inf)) = NaN", __real__ result);
check_isnan ("imag(ccosh(NaN - i Inf)) = NaN", __imag__ result);
result = FUNC(ccosh) (BUILD_COMPLEX (nan_value, nan_value));
check_isnan ("real(ccosh(NaN + i NaN)) = NaN", __real__ result);
check_isnan ("imag(ccosh(NaN + i NaN)) = NaN", __imag__ result);
}
#if 0
/* Enable these tests as soon as the functions are available. */
static void
cacos_test (void)
{
__complex__ MATHTYPE result;
result = FUNC(cacos) (BUILD_COMPLEX (0, 0));
check ("real(cacos(0 + i0)) = pi/2", __real__ result, M_PI_2);
check ("imag(cacos(0 + i0)) = -0", __imag__ result, minus_zero);
result = FUNC(cacos) (BUILD_COMPLEX (minus_zero, 0));
check ("real(cacos(-0 + i0)) = pi/2", __real__ result, M_PI_2);
check ("imag(cacos(-0 + i0)) = -0", __imag__ result, minus_zero);
result = FUNC(cacos) (BUILD_COMPLEX (0, minus_zero));
check ("real(cacos(0 - i0)) = pi/2", __real__ result, M_PI_2);
check ("imag(cacos(0 - i0)) = 0", __imag__ result, 0);
result = FUNC(cacos) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(cacos(-0 - i0)) = pi/2", __real__ result, M_PI_2);
check ("imag(cacos(-0 - i0)) = 0", __imag__ result, 0);
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, plus_infty));
check ("real(cacos(-Inf + i Inf)) = 3*pi/4", __real__ result, M_PI - M_PI_4);
check_isinfn ("imag(cacos(-Inf + i Inf)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, minus_infty));
check ("real(cacos(-Inf - i Inf)) = 3*pi/4", __real__ result, M_PI - M_PI_4);
check_isinfp ("imag(cacos(-Inf - i Inf)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, plus_infty));
check ("real(cacos(+Inf + i Inf)) = pi/4", __real__ result, M_PI_4);
check_isinfn ("imag(cacos(+Inf + i Inf)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, minus_infty));
check ("real(cacos(+Inf - i Inf)) = pi/4", __real__ result, M_PI_4);
check_isinfp ("imag(cacos(+Inf - i Inf)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (-10.0, plus_infty));
check ("real(cacos(-10.0 + i Inf)) = pi/2", __real__ result, M_PI_2);
check_isinfn ("imag(cacos(-10.0 + i Inf)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (-10.0, minus_infty));
check ("real(cacos(-10.0 - i Inf)) = pi/2", __real__ result, M_PI_2);
check_isinfp ("imag(cacos(-10.0 - i Inf)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (0, plus_infty));
check ("real(cacos(0 + i Inf)) = pi/2", __real__ result, M_PI_2);
check_isinfn ("imag(cacos(0 + i Inf)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (0, minus_infty));
check ("real(cacos(0 - i Inf)) = pi/2", __real__ result, M_PI_2);
check_isinfp ("imag(cacos(0 - i Inf)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (0.1, plus_infty));
check ("real(cacos(0.1 + i Inf)) = pi/2", __real__ result, M_PI_2);
check_isinfn ("imag(cacos(0.1 + i Inf)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (0.1, minus_infty));
check ("real(cacos(0.1 - i Inf)) = pi/2", __real__ result, M_PI_2);
check_isinfp ("imag(cacos(0.1 - i Inf)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, 0));
check ("real(cacos(-Inf + i0)) = pi", __real__ result, M_PI);
check_isinfn ("imag(cacos(-Inf + i0)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, minus_zero));
check ("real(cacos(-Inf - i0)) = pi", __real__ result, M_PI);
check_isinfp ("imag(cacos(-Inf - i0)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, 100));
check ("real(cacos(-Inf + i100)) = pi", __real__ result, M_PI);
check_isinfn ("imag(cacos(-Inf + i100)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, -100));
check ("real(cacos(-Inf - i100)) = pi", __real__ result, M_PI);
check_isinfp ("imag(cacos(-Inf - i100)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, 0));
check ("real(cacos(+Inf + i0)) = 0", __real__ result, 0);
check_isinfn ("imag(cacos(+Inf + i0)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, minus_zero));
check ("real(cacos(+Inf - i0)) = 0", __real__ result, 0);
check_isinfp ("imag(cacos(+Inf - i0)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, 0.5));
check ("real(cacos(+Inf + i0.5)) = 0", __real__ result, 0);
check_isinfn ("imag(cacos(+Inf + i0.5)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, -0.5));
check ("real(cacos(+Inf - i0.5)) = 0", __real__ result, 0);
check_isinfp ("imag(cacos(+Inf - i0.5)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (plus_infty, nan_value));
check_isnan ("real(cacos(+Inf + i NaN)) = NaN", __real__ result);
check_isinfp ("imag(cacos(+Inf + i NaN)) = +-Inf",
FUNC(fabs) (__imag__ result));
result = FUNC(cacos) (BUILD_COMPLEX (minus_infty, nan_value));
check_isnan ("real(cacos(-Inf + i NaN)) = NaN", __real__ result);
check_isinfp ("imag(cacos(-Inf + i NaN)) = +-Inf",
FUNC(fabs) (__imag__ result));
result = FUNC(cacos) (BUILD_COMPLEX (0, nan_value));
check ("real(cacos(0 + i NaN)) = pi/2", __real__ result, M_PI_2);
check_isnan ("imag(cacos(0 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (minus_zero, nan_value));
check ("real(cacos(-0 + i NaN)) = pi/2", __real__ result, M_PI_2);
check_isnan ("imag(cacos(-0 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (nan_value, plus_infty));
check_isnan ("real(cacos(NaN + i Inf)) = NaN", __real__ result);
check_isinfn ("imag(cacos(NaN + i Inf)) = -Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (nan_value, minus_infty));
check_isnan ("real(cacos(NaN - i Inf)) = NaN", __real__ result);
check_isinfp ("imag(cacos(NaN - i Inf)) = +Inf", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (10.5, nan_value));
check_isnan ("real(cacos(10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacos(10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(cacos(-10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacos(-10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (nan_value, 0.75));
check_isnan ("real(cacos(NaN + i0.75)) = NaN", __real__ result);
check_isnan ("imag(cacos(NaN + i0.75)) = NaN", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(cacos(NaN - i0.75)) = NaN", __real__ result);
check_isnan ("imag(cacos(NaN - i0.75)) = NaN", __imag__ result);
result = FUNC(cacos) (BUILD_COMPLEX (nan_value, nan_value));
check_isnan ("real(cacos(NaN + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacos(NaN + i NaN)) = NaN", __imag__ result);
}
static void
cacosh_test (void)
{
__complex__ MATHTYPE result;
result = FUNC(cacosh) (BUILD_COMPLEX (0, 0));
check ("real(cacosh(0 + i0)) = 0", __real__ result, 0);
check ("imag(cacosh(0 + i0)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_zero, 0));
check ("real(cacosh(-0 + i0)) = 0", __real__ result, 0);
check ("imag(cacosh(-0 + i0)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (0, minus_zero));
check ("real(cacosh(0 - i0)) = 0", __real__ result, 0);
check ("imag(cacosh(0 - i0)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(cacosh(-0 - i0)) = 0", __real__ result, 0);
check ("imag(cacosh(-0 - i0)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, plus_infty));
check_isinfp ("real(cacosh(-Inf + i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(-Inf + i Inf)) = 3*pi/4", __imag__ result,
M_PI - M_PI_4);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, minus_infty));
check_isinfp ("real(cacosh(-Inf - i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(-Inf - i Inf)) = -3*pi/4", __imag__ result,
M_PI_4 - M_PI);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, plus_infty));
check_isinfp ("real(cacosh(+Inf + i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(+Inf + i Inf)) = pi/4", __imag__ result, M_PI_4);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, minus_infty));
check_isinfp ("real(cacosh(+Inf - i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(+Inf - i Inf)) = -pi/4", __imag__ result, -M_PI_4);
result = FUNC(cacosh) (BUILD_COMPLEX (-10.0, plus_infty));
check_isinfp ("real(cacosh(-10.0 + i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(-10.0 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (-10.0, minus_infty));
check_isinfp ("real(cacosh(-10.0 - i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(-10.0 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (0, plus_infty));
check_isinfp ("real(cacosh(0 + i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(0 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (0, minus_infty));
check_isinfp ("real(cacosh(0 - i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(0 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (0.1, plus_infty));
check_isinfp ("real(cacosh(0.1 + i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(0.1 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (0.1, minus_infty));
check_isinfp ("real(cacosh(0.1 - i Inf)) = +Inf", __real__ result);
check ("imag(cacosh(0.1 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, 0));
check_isinfp ("real(cacosh(-Inf + i0)) = +Inf", __real__ result);
check ("imag(cacosh(-Inf + i0)) = pi", __imag__ result, M_PI);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, minus_zero));
check_isinfp ("real(cacosh(-Inf - i0)) = +Inf", __real__ result);
check ("imag(cacosh(-Inf - i0)) = -pi", __imag__ result, -M_PI);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, 100));
check_isinfp ("real(cacosh(-Inf + i100)) = +Inf", __real__ result);
check ("imag(cacosh(-Inf + i100)) = pi", __imag__ result, M_PI);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, -100));
check_isinfp ("real(cacosh(-Inf - i100)) = +Inf", __real__ result);
check ("imag(cacosh(-Inf - i100)) = -pi", __imag__ result, -M_PI);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, 0));
check_isinfp ("real(cacosh(+Inf + i0)) = +Inf", __real__ result);
check ("imag(cacosh(+Inf + i0)) = 0", __imag__ result, 0);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, minus_zero));
check_isinfp ("real(cacosh(+Inf - i0)) = +Inf", __real__ result);
check ("imag(cacosh(+Inf - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, 0.5));
check_isinfp ("real(cacosh(+Inf + i0.5)) = +Inf", __real__ result);
check ("imag(cacosh(+Inf + i0.5)) = 0", __imag__ result, 0);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, -0.5));
check_isinfp ("real(cacosh(+Inf - i0.5)) = +Inf", __real__ result);
check ("imag(cacosh(+Inf - i0.5)) = -0", __imag__ result, minus_zero);
result = FUNC(cacosh) (BUILD_COMPLEX (plus_infty, nan_value));
check_isinfp ("real(cacosh(+Inf + i NaN)) = +Inf", __real__ result);
check_isnan ("imag(cacosh(+Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_infty, nan_value));
check_isinfp ("real(cacosh(-Inf + i NaN)) = +Inf", __real__ result);
check_isnan ("imag(cacosh(-Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (0, nan_value));
check_isnan ("real(cacosh(0 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacosh(0 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (minus_zero, nan_value));
check_isnan ("real(cacosh(-0 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacosh(-0 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (nan_value, plus_infty));
check_isinfp ("real(cacosh(NaN + i Inf)) = +Inf", __real__ result);
check_isnan ("imag(cacosh(NaN + i Inf)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (nan_value, minus_infty));
check_isinfp ("real(cacosh(NaN - i Inf)) = +Inf", __real__ result);
check_isnan ("imag(cacosh(NaN - i Inf)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (10.5, nan_value));
check_isnan ("real(cacosh(10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacosh(10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(cacosh(-10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacosh(-10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (nan_value, 0.75));
check_isnan ("real(cacosh(NaN + i0.75)) = NaN", __real__ result);
check_isnan ("imag(cacosh(NaN + i0.75)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(cacosh(NaN - i0.75)) = NaN", __real__ result);
check_isnan ("imag(cacosh(NaN - i0.75)) = NaN", __imag__ result);
result = FUNC(cacosh) (BUILD_COMPLEX (nan_value, nan_value));
check_isnan ("real(cacosh(NaN + i NaN)) = NaN", __real__ result);
check_isnan ("imag(cacosh(NaN + i NaN)) = NaN", __imag__ result);
}
static void
casinh_test (void)
{
__complex__ MATHTYPE result;
result = FUNC(casinh) (BUILD_COMPLEX (0, 0));
check ("real(casinh(0 + i0)) = 0", __real__ result, 0);
check ("imag(casinh(0 + i0)) = 0", __imag__ result, 0);
result = FUNC(casinh) (BUILD_COMPLEX (minus_zero, 0));
check ("real(casinh(-0 + i0)) = -0", __real__ result, minus_zero);
check ("imag(casinh(-0 + i0)) = 0", __imag__ result, 0);
result = FUNC(casinh) (BUILD_COMPLEX (0, minus_zero));
check ("real(casinh(0 - i0)) = 0", __real__ result, 0);
check ("imag(casinh(0 - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(casinh(-0 - i0)) = -0", __real__ result, minus_zero);
check ("imag(casinh(-0 - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, plus_infty));
check_isinfp ("real(casinh(+Inf + i Inf)) = +Inf", __real__ result);
check ("imag(casinh(+Inf + i Inf)) = pi/4", __imag__ result, M_PI_4);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, minus_infty));
check_isinfp ("real(casinh(+Inf - i Inf)) = +Inf", __real__ result);
check ("imag(casinh(+Inf - i Inf)) = -pi/4", __imag__ result, -M_PI_4);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, plus_infty));
check_isinfn ("real(casinh(-Inf + i Inf)) = -Inf", __real__ result);
check ("imag(casinh(-Inf + i Inf)) = pi/4", __imag__ result, M_PI_4);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, minus_infty));
check_isinfn ("real(casinh(-Inf - i Inf)) = -Inf", __real__ result);
check ("imag(casinh(-Inf - i Inf)) = -pi/4", __imag__ result, -M_PI_4);
result = FUNC(casinh) (BUILD_COMPLEX (-10.0, plus_infty));
check_isinfn ("real(casinh(-10.0 + i Inf)) = -Inf", __real__ result);
check ("imag(casinh(-10.0 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(casinh) (BUILD_COMPLEX (-10.0, minus_infty));
check_isinfn ("real(casinh(-10.0 - i Inf)) = -Inf", __real__ result);
check ("imag(casinh(-10.0 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(casinh) (BUILD_COMPLEX (0, plus_infty));
check_isinfp ("real(casinh(0 + i Inf)) = +Inf", __real__ result);
check ("imag(casinh(0 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(casinh) (BUILD_COMPLEX (0, minus_infty));
check_isinfp ("real(casinh(0 - i Inf)) = +Inf", __real__ result);
check ("imag(casinh(0 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(casinh) (BUILD_COMPLEX (0.1, plus_infty));
check_isinfp ("real(casinh(0.1 + i Inf)) = +Inf", __real__ result);
check ("imag(casinh(0.1 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(casinh) (BUILD_COMPLEX (0.1, minus_infty));
check_isinfp ("real(casinh(0.1 - i Inf)) = +Inf", __real__ result);
check ("imag(casinh(0.1 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, 0));
check_isinfn ("real(casinh(-Inf + i0)) = -Inf", __real__ result);
check ("imag(casinh(-Inf + i0)) = 0", __imag__ result, 0);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, minus_zero));
check_isinfn ("real(casinh(-Inf - i0)) = -Inf", __real__ result);
check ("imag(casinh(-Inf - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, 100));
check_isinfn ("real(casinh(-Inf + i100)) = -Inf", __real__ result);
check ("imag(casinh(-Inf + i100)) = 0", __imag__ result, 0);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, -100));
check_isinfn ("real(casinh(-Inf - i100)) = -Inf", __real__ result);
check ("imag(casinh(-Inf - i100)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, 0));
check_isinfp ("real(casinh(+Inf + i0)) = +Inf", __real__ result);
check ("imag(casinh(+Inf + i0)) = 0", __imag__ result, 0);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, minus_zero));
check_isinfp ("real(casinh(+Inf - i0)) = +Inf", __real__ result);
check ("imag(casinh(+Inf - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, 0.5));
check_isinfp ("real(casinh(+Inf + i0.5)) = +Inf", __real__ result);
check ("imag(casinh(+Inf + i0.5)) = 0", __imag__ result, 0);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, -0.5));
check_isinfp ("real(casinh(+Inf - i0.5)) = +Inf", __real__ result);
check ("imag(casinh(+Inf - i0.5)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (plus_infty, nan_value));
check_isinfp ("real(casinh(+Inf + i NaN)) = +Inf", __real__ result);
check_isnan ("imag(casinh(+Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (minus_infty, nan_value));
check_isinfn ("real(casinh(-Inf + i NaN)) = -Inf", __real__ result);
check_isnan ("imag(casinh(-Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (nan_value, 0));
check_isnan ("real(casinh(NaN + i0)) = NaN", __real__ result);
check ("imag(casinh(NaN + i0)) = 0", __imag__ resul, 0);
result = FUNC(casinh) (BUILD_COMPLEX (minus_zero, nan_value));
check_isnan ("real(casinh(NaN - i0)) = NaN", __real__ result);
check ("imag(casinh(NaN - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(casinh) (BUILD_COMPLEX (nan_value, plus_infty));
check_isinfp ("real(casinh(NaN + i Inf)) = +Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(casinh(NaN + i Inf)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (nan_value, minus_infty));
check_isinfp ("real(casinh(NaN - i Inf)) = +Inf",
FUNC(fabs) (__real__ result));
check_isnan ("imag(casinh(NaN - i Inf)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (10.5, nan_value));
check_isnan ("real(casinh(10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(casinh(10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(casinh(-10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(casinh(-10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (nan_value, 0.75));
check_isnan ("real(casinh(NaN + i0.75)) = NaN", __real__ result);
check_isnan ("imag(casinh(NaN + i0.75)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(casinh(NaN - i0.75)) = NaN", __real__ result);
check_isnan ("imag(casinh(NaN - i0.75)) = NaN", __imag__ result);
result = FUNC(casinh) (BUILD_COMPLEX (nan_value, nan_value));
check_isnan ("real(casinh(NaN + i NaN)) = NaN", __real__ result);
check_isnan ("imag(casinh(NaN + i NaN)) = NaN", __imag__ result);
}
static void
catanh_test (void)
{
__complex__ MATHTYPE result;
result = FUNC(catanh) (BUILD_COMPLEX (0, 0));
check ("real(catanh(0 + i0)) = 0", __real__ result, 0);
check ("imag(catanh(0 + i0)) = 0", __imag__ result, 0);
result = FUNC(catanh) (BUILD_COMPLEX (minus_zero, 0));
check ("real(catanh(-0 + i0)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-0 + i0)) = 0", __imag__ result, 0);
result = FUNC(catanh) (BUILD_COMPLEX (0, minus_zero));
check ("real(catanh(0 - i0)) = 0", __real__ result, 0);
check ("imag(catanh(0 - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(catanh) (BUILD_COMPLEX (minus_zero, minus_zero));
check ("real(catanh(-0 - i0)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-0 - i0)) = -0", __imag__ result, minus_zero);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, plus_infty));
check ("real(catanh(+Inf + i Inf)) = 0", __real__ result, 0);
check ("imag(catanh(+Inf + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, minus_infty));
check ("real(catanh(+Inf - i Inf)) = 0", __real__ result, 0);
check ("imag(catanh(+Inf - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, plus_infty));
check ("real(catanh(-Inf + i Inf)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-Inf + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, minus_infty));
check ("real(catanh(-Inf - i Inf)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-Inf - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (-10.0, plus_infty));
check ("real(catanh(-10.0 + i Inf)) = -0", __real__ result, -minus_zero);
check ("imag(catanh(-10.0 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (-10.0, minus_infty));
check ("real(catanh(-10.0 - i Inf)) = -0", __real__ result, minus_infty);
check ("imag(catanh(-10.0 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (0, plus_infty));
check ("real(catanh(0 + i Inf)) = 0", __real__ result, 0);
check ("imag(catanh(0 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (0, minus_infty));
check ("real(catanh(0 - i Inf)) = 0", __real__ result, 0);
check ("imag(catanh(0 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (0.1, plus_infty));
check ("real(catanh(0.1 + i Inf)) = 0", __real__ result, 0);
check ("imag(catanh(0.1 + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (0.1, minus_infty));
check ("real(catanh(0.1 - i Inf)) = 0", __real__ result, 0);
check ("imag(catanh(0.1 - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, 0));
check ("real(catanh(-Inf + i0)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-Inf + i0)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, minus_zero));
check ("real(catanh(-Inf - i0)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-Inf - i0)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, 100));
check ("real(catanh(-Inf + i100)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-Inf + i100)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, -100));
check ("real(catanh(-Inf - i100)) = -0", __real__ result, minus_zero);
check ("imag(catanh(-Inf - i100)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, 0));
check ("real(catanh(+Inf + i0)) = 0", __real__ result, 0);
check ("imag(catanh(+Inf + i0)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, minus_zero));
check ("real(catanh(+Inf - i0)) = 0", __real__ result, 0);
check ("imag(catanh(+Inf - i0)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, 0.5));
check ("real(catanh(+Inf + i0.5)) = 0", __real__ result, 0);
check ("imag(catanh(+Inf + i0.5)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, -0.5));
check ("real(catanh(+Inf - i0.5)) = 0", __real__ result, 0);
check ("imag(catanh(+Inf - i0.5)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (0, nan_value));
check ("real(catanh(0 + i NaN)) = 0", __real__ result, 0);
check_isnan ("imag(catanh(+Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (minus_zero, nan_value));
check ("real(catanh(-0 + i NaN)) = -0", __real__ result, minus_zero);
check_isnan ("imag(catanh(-Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (plus_infty, nan_value));
check ("real(catanh(+Inf + i NaN)) = 0", __real__ result, 0);
check_isnan ("imag(catanh(+Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (minus_infty, nan_value));
check ("real(catanh(-Inf + i NaN)) = -0", __real__ result, minus_zero);
check_isnan ("imag(catanh(-Inf + i NaN)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (nan_value, 0));
check_isnan ("real(catanh(NaN + i0)) = NaN", __real__ result);
check_isnan ("imag(catanh(NaN + i0)) = NaN", __imag__ resul);
result = FUNC(catanh) (BUILD_COMPLEX (minus_zero, nan_value));
check_isnan ("real(catanh(NaN - i0)) = NaN", __real__ result);
check_isnan ("imag(catanh(NaN - i0)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (nan_value, plus_infty));
check ("real(catanh(NaN + i Inf)) = +-0", FUNC(fabs) (__real__ result), 0);
check ("imag(catanh(NaN + i Inf)) = pi/2", __imag__ result, M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (nan_value, minus_infty));
check ("real(catanh(NaN - i Inf)) = +-0", FUNC(fabs) (__real__ result), 0);
check ("imag(catanh(NaN - i Inf)) = -pi/2", __imag__ result, -M_PI_2);
result = FUNC(catanh) (BUILD_COMPLEX (10.5, nan_value));
check_isnan ("real(catanh(10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(catanh(10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(catanh(-10.5 + i NaN)) = NaN", __real__ result);
check_isnan ("imag(catanh(-10.5 + i NaN)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (nan_value, 0.75));
check_isnan ("real(catanh(NaN + i0.75)) = NaN", __real__ result);
check_isnan ("imag(catanh(NaN + i0.75)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (-10.5, nan_value));
check_isnan ("real(catanh(NaN - i0.75)) = NaN", __real__ result);
check_isnan ("imag(catanh(NaN - i0.75)) = NaN", __imag__ result);
result = FUNC(catanh) (BUILD_COMPLEX (nan_value, nan_value));
check_isnan ("real(catanh(NaN + i NaN)) = NaN", __real__ result);
check_isnan ("imag(catanh(NaN + i NaN)) = NaN", __imag__ result);
}
#endif
static void
inverse_func_pair_test (const char *test_name,
mathfunc f1, mathfunc inverse,
@ -1943,6 +2697,8 @@ main (int argc, char *argv[])
remquo_test ();
#endif
cexp_test ();
csinh_test ();
ccosh_test ();
identities ();
inverse_functions ();

View File

@ -64,7 +64,7 @@ install-lib := libbsd-compat.a libg.a
non-lib.a := libbsd-compat.a
gpl2lgpl := error.c error.h
tests := tst-dirname
tests := tst-dirname tst-tsearch
include ../Rules
@ -77,3 +77,9 @@ $(objpfx)libg.a: $(dep-dummy-lib); $(make-dummy-lib)
CFLAGS-init-misc.c = -fkeep-inline-functions
ifeq ($(build-shared),yes)
$(objpfx)tst-tsearch: $(common-objpfx)math/libm.so$(libm.so-version)
else
$(objpfx)tst-tsearch: $(common-objpfx)math/libm.a
endif

View File

@ -1,5 +1,6 @@
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@ -16,175 +17,584 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Tree search generalized from Knuth (6.2.2) Algorithm T just like
the AT&T man page says.
The node_t structure is for internal use only, lint doesn't grok it.
Written by reading the System V Interface Definition, not the code.
/* Tree search for red/black trees.
The algorithm for adding nodes is taken from one of the many "Algorithms"
books by Robert Sedgewick, although the implementation differs.
The algorithm for deleting nodes can probably be found in a book named
"Introduction to Algorithms" by Cormen/Leiserson/Rivest. At least that's
the book that my professor took most algorithms from during the "Data
Structures" course...
Totally public domain. */
/*LINTLIBRARY*/
/* Red/black trees are binary trees in which the edges are colored either red
or black. They have the following properties:
1. The number of black edges on every path from the root to a leaf is
constant.
2. No two red edges are adjacent.
Therefore there is an upper bound on the length of every path, it's
O(log n) where n is the number of nodes in the tree. No path can be longer
than 1+2*P where P is the length of the shortest path in the tree.
Useful for the implementation:
3. If one of the children of a node is NULL, then the other one is red
(if it exists).
In the implementation, not the edges are colored, but the nodes. The color
interpreted as the color of the edge leading to this node. The color is
meaningless for the root node, but we color the root node black for
convenience. All added nodes are red initially.
Adding to a red/black tree is rather easy. The right place is searched
with a usual binary tree search. Additionally, whenever a node N is
reached that has two red successors, the successors are colored black and
the node itself colored red. This moves red edges up the tree where they
pose less of a problem once we get to really insert the new node. Changing
N's color to red may violate rule 2, however, so rotations may become
necessary to restore the invariants. Adding a new red leaf may violate
the same rule, so afterwards an additional check is run and the tree
possibly rotated.
Deleting is hairy. There are mainly two nodes involved: the node to be
deleted (n1), and another node that is to be unchained from the tree (n2).
If n1 has a successor (the node with a smallest key that is larger than
n1), then the successor becomes n2 and its contents are copied into n1,
otherwise n1 becomes n2.
Unchaining a node may violate rule 1: if n2 is black, one subtree is
missing one black edge afterwards. The algorithm must try to move this
error upwards towards the root, so that the subtree that does not have
enough black edges becomes the whole tree. Once that happens, the error
has disappeared. It may not be necessary to go all the way up, since it
is possible that rotations and recoloring can fix the error before that.
Although the deletion algorithm must walk upwards through the tree, we
do not store parent pointers in the nodes. Instead, delete allocates a
small array of parent pointers and fills it while descending the tree.
Since we know that the length of a path is O(log n), where n is the number
of nodes, this is likely to use less memory. */
/* Tree rotations look like this:
A C
/ \ / \
B C A G
/ \ / \ --> / \
D E F G B F
/ \
D E
In this case, A has been rotated left. This preserves the ordering of the
binary tree. */
#include <stdlib.h>
#include <search.h>
/* This routine is not very bad. It makes many assumptions about
the compiler. It assumes that the first field in the node must be
the "key" field, which points to the datum. It is very tricky
stuff. H.J. */
typedef struct node_t
{
/* Callers expect this to be the first element in the structure - do not
move! */
const void *key;
struct node_t *left;
struct node_t *right;
}
node;
unsigned int red:1;
} *node;
/* Prototype fpr local function. */
static void trecurse __P ((const void *vroot, __action_fn_t action, int level));
#undef DEBUGGING
#ifdef DEBUGGING
/* find or insert datum into search tree.
char *key; key to be located
node **rootp; address of tree root
int (*compar)(); ordering function
*/
void *
__tsearch (key, vrootp, compar)
const void *key;
void **vrootp;
__compar_fn_t compar;
/* Routines to check tree invariants. */
#include <assert.h>
#define CHECK_TREE(a) check_tree(a)
static void
check_tree_recurse (node p, int d_sofar, int d_total)
{
node *q;
node **rootp = (node **) vrootp;
if (p == NULL)
{
assert (d_sofar == d_total);
return;
}
check_tree_recurse (p->left, d_sofar + (p->left && !p->left->red), d_total);
check_tree_recurse (p->right, d_sofar + (p->right && !p->right->red), d_total);
if (p->left)
assert (!(p->left->red && p->red));
if (p->right)
assert (!(p->right->red && p->red));
}
static void
check_tree (node root)
{
int cnt = 0;
node p;
if (root == NULL)
return;
root->red = 0;
for(p = root->left; p; p = p->left)
cnt += !p->red;
check_tree_recurse (root, 0, cnt);
}
#else
#define CHECK_TREE(a)
#endif
/* Possibly "split" a node with two red successors, and/or fix up two red
edges in a row. ROOTP is a pointer to the lowest node we visited, PARENTP
and GPARENTP pointers to its parent/grandparent. P_R and GP_R contain the
comparison values that determined which way was taken in the tree to reach
ROOTP. MODE is 1 if we need not do the split, but must check for two red
edges between GPARENTP and ROOTP. */
static void
maybe_split_for_insert (node *rootp, node *parentp, node *gparentp,
int p_r, int gp_r, int mode)
{
node root = *rootp;
node *rp, *lp;
rp = &(*rootp)->right;
lp = &(*rootp)->left;
/* See if we have to split this node (both successors red). */
if (mode == 1
|| ((*rp) != NULL && (*lp) != NULL && (*rp)->red && (*lp)->red))
{
/* This node becomes red, its successors black. */
root->red = 1;
if (*rp)
(*rp)->red = 0;
if (*lp)
(*lp)->red = 0;
/* If the parent of this node is also red, we have to do
rotations. */
if (parentp != NULL && (*parentp)->red)
{
node gp = *gparentp;
node p = *parentp;
/* There are two main cases:
1. The edge types (left or right) of the two red edges differ.
2. Both red edges are of the same type.
There exist two symmetries of each case, so there is a total of
4 cases. */
if ((p_r > 0) != (gp_r > 0))
{
/* Put the child at the top of the tree, with its parent
and grandparent as successors. */
p->red = 1;
gp->red = 1;
root->red = 0;
if (p_r < 0)
{
/* Child is left of parent. */
p->left = *rp;
*rp = p;
gp->right = *lp;
*lp = gp;
}
else
{
/* Child is right of parent. */
p->right = *lp;
*lp = p;
gp->left = *rp;
*rp = gp;
}
*gparentp = root;
}
else
{
*gparentp = *parentp;
/* Parent becomes the top of the tree, grandparent and
child are its successors. */
p->red = 0;
gp->red = 1;
if (p_r < 0)
{
/* Left edges. */
gp->left = p->right;
p->right = gp;
}
else
{
/* Right edges. */
gp->right = p->left;
p->left = gp;
}
}
}
}
}
/* Find or insert datum into search tree.
KEY is the key to be located, ROOTP is the address of tree root,
COMPAR the ordering function. */
void *
__tsearch (const void *key, void **vrootp, __compar_fn_t compar)
{
node q;
node *parentp = NULL, *gparentp = NULL;
node *rootp = (node *) vrootp;
node *nextp;
int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler. */
if (rootp == NULL)
return NULL;
while (*rootp != NULL) /* Knuth's T1: */
{
int r;
/* This saves some additional tests below. */
if (*rootp != NULL)
(*rootp)->red = 0;
r = (*compar) (key, (*rootp)->key);
if (r == 0) /* T2: */
return *rootp; /* we found it! */
rootp = (r < 0)
? &(*rootp)->left /* T3: follow left branch */
: &(*rootp)->right; /* T4: follow right branch */
CHECK_TREE (*rootp);
nextp = rootp;
while (*nextp != NULL)
{
node root = *rootp;
r = (*compar) (key, root->key);
if (r == 0)
return root;
maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
/* If that did any rotations, parentp and gparentp are now garbage.
That doesn't matter, because the values they contain are never
used again in that case. */
nextp = r < 0 ? &root->left : &root->right;
if (*nextp == NULL)
break;
gparentp = parentp;
parentp = rootp;
rootp = nextp;
gp_r = p_r;
p_r = r;
}
q = (node *) malloc (sizeof (node)); /* T5: key not found */
if (q != NULL) /* make new node */
q = (struct node_t *) malloc (sizeof (struct node_t));
if (q != NULL)
{
*rootp = q; /* link new node to old */
*nextp = q; /* link new node to old */
q->key = key; /* initialize new node */
q->red = 1;
q->left = q->right = NULL;
}
if (nextp != rootp)
/* There may be two red edges in a row now, which we must avoid by
rotating the tree. */
maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
return q;
}
weak_alias (__tsearch, tsearch)
/* Find datum in search tree.
KEY is the key to be located, ROOTP is the address of tree root,
COMPAR the ordering function. */
void *
__tfind (key, vrootp, compar)
const void *key;
const void **vrootp;
__compar_fn_t compar;
{
node **rootp = (node **) vrootp;
node *rootp = (node *) vrootp;
if (rootp == NULL)
return NULL;
while (*rootp != NULL) /* Knuth's T1: */
CHECK_TREE (*rootp);
while (*rootp != NULL)
{
node root = *rootp;
int r;
r = (*compar)(key, (*rootp)->key);
if (r == 0) /* T2: */
return *rootp; /* we found it! */
r = (*compar) (key, root->key);
if (r == 0)
return root;
rootp = (r < 0)
? &(*rootp)->left /* T3: follow left branch */
: &(*rootp)->right; /* T4: follow right branch */
rootp = r < 0 ? &root->left : &root->right;
}
return NULL;
return NULL;
}
weak_alias (__tfind, tfind)
/* delete node with given key
char *key; key to be deleted
node **rootp; address of the root of tree
int (*compar)(); comparison function
*/
/* Delete node with given key.
KEY is the key to be deleted, ROOTP is the address of the root of tree,
COMPAR the comparison function. */
void *
__tdelete (key, vrootp, compar)
const void *key;
void **vrootp;
__compar_fn_t compar;
__tdelete (const void *key, void **vrootp, __compar_fn_t compar)
{
node *p;
node *q;
node *r;
node p, q, r, retval;
int cmp;
node **rootp = (node **) vrootp;
node *rootp = (node *) vrootp;
node root, unchained;
/* Stack of nodes so we remember the parents without recursion. It's
_very_ unlikely that there are paths longer than 40 nodes. The tree
would need to have around 250.000 nodes. */
int stacksize = 40;
int sp = 0;
node **nodestack = alloca (sizeof (node *) * stacksize);
if (rootp == NULL || (p = *rootp) == NULL)
if (rootp == NULL)
return NULL;
p = *rootp;
if (p == NULL)
return NULL;
CHECK_TREE (p);
while ((cmp = (*compar) (key, (*rootp)->key)) != 0)
{
if (sp == stacksize)
{
node **newstack;
stacksize += 20;
newstack = alloca (sizeof (node *) * stacksize);
memcpy (newstack, nodestack, sp * sizeof (node *));
nodestack = newstack;
}
nodestack[sp++] = rootp;
p = *rootp;
rootp = (cmp < 0)
? &(*rootp)->left /* follow left branch */
: &(*rootp)->right; /* follow right branch */
rootp = ((cmp < 0)
? &(*rootp)->left
: &(*rootp)->right);
if (*rootp == NULL)
return NULL; /* key not found */
return NULL;
}
r = (*rootp)->right; /* D1: */
q = (*rootp)->left;
if (q == NULL) /* Left NULL? */
q = r;
else if (r != NULL) /* Right link is NULL? */
/* This is bogus if the node to be deleted is the root... this routine
really should return an integer with 0 for success, -1 for failure
and errno = ESRCH or something. */
retval = p;
/* We don't unchain the node we want to delete. Instead, we overwrite
it with its successor and unchain the successor. If there is no
successor, we really unchain the node to be deleted. */
root = *rootp;
r = root->right;
q = root->left;
if (q == NULL || r == NULL)
unchained = root;
else
{
if (r->left == NULL) /* D2: Find successor */
node *parent = rootp, *up = &root->right;
for (;;)
{
r->left = q;
q = r;
}
else
{ /* D3: Find (struct node_t *)0 link */
for (q = r->left; q->left != NULL; q = r->left)
r = q;
r->left = q->right;
q->left = (*rootp)->left;
q->right = (*rootp)->right;
if (sp == stacksize)
{
node **newstack;
stacksize += 20;
newstack = alloca (sizeof (node *) * stacksize);
memcpy (newstack, nodestack, sp * sizeof (node *));
nodestack = newstack;
}
nodestack[sp++] = parent;
parent = up;
if ((*up)->left == NULL)
break;
up = &(*up)->left;
}
unchained = *up;
}
free ((struct node_t *) *rootp); /* D4: Free node */
*rootp = q; /* link parent to new node */
return p;
/* We know that either the left or right successor of UNCHAINED is NULL.
R becomes the other one, it is chained into the parent of UNCHAINED. */
r = unchained->left;
if (r == NULL)
r = unchained->right;
if (sp == 0)
*rootp = r;
else
{
q = *nodestack[sp-1];
if (unchained == q->right)
q->right = r;
else
q->left = r;
}
if (unchained != root)
root->key = unchained->key;
if (!unchained->red)
{
/* Now we lost a black edge, which means that the number of black
edges on every path is no longer constant. We must balance the
tree. */
/* NODESTACK now contains all parents of R. R is likely to be NULL
in the first iteration. */
/* NULL nodes are considered black throughout - this is necessary for
correctness. */
while (sp > 0 && (r == NULL || !r->red))
{
node *pp = nodestack[sp - 1];
p = *pp;
/* Two symmetric cases. */
if (r == p->left)
{
/* Q is R's brother, P is R's parent. The subtree with root
R has one black edge less than the subtree with root Q. */
q = p->right;
if (q != NULL && q->red)
{
/* If Q is red, we know that P is black. We rotate P left
so that Q becomes the top node in the tree, with P below
it. P is colored red, Q is colored black.
This action does not change the black edge count for any
leaf in the tree, but we will be able to recognize one
of the following situations, which all require that Q
is black. */
q->red = 0;
p->red = 1;
/* Left rotate p. */
p->right = q->left;
q->left = p;
*pp = q;
/* Make sure pp is right if the case below tries to use
it. */
nodestack[sp++] = pp = &q->left;
q = p->right;
}
/* We know that Q can't be NULL here. We also know that Q is
black. */
if ((q->left == NULL || !q->left->red)
&& (q->right == NULL || !q->right->red))
{
/* Q has two black successors. We can simply color Q red.
The whole subtree with root P is now missing one black
edge. Note that this action can temporarily make the
tree invalid (if P is red). But we will exit the loop
in that case and set P black, which both makes the tree
valid and also makes the black edge count come out
right. If P is black, we are at least one step closer
to the root and we'll try again the next iteration. */
q->red = 1;
r = p;
}
else
{
/* Q is black, one of Q's successors is red. We can
repair the tree with one operation and will exit the
loop afterwards. */
if (q->right == NULL || !q->right->red)
{
/* The left one is red. We perform the same action as
in maybe_split_for_insert where two red edges are
adjacent but point in different directions:
Q's left successor (let's call it Q2) becomes the
top of the subtree we are looking at, its parent (Q)
and grandparent (P) become its successors. The former
successors of Q2 are placed below P and Q.
P becomes black, and Q2 gets the color that P had.
This changes the black edge count only for node R and
its successors. */
node q2 = q->left;
q2->red = p->red;
p->right = q2->left;
q->left = q2->right;
q2->right = q;
q2->left = p;
*pp = q2;
p->red = 0;
}
else
{
/* It's the right one. Rotate P left. P becomes black,
and Q gets the color that P had. Q's right successor
also becomes black. This changes the black edge
count only for node R and its successors. */
q->red = p->red;
p->red = 0;
q->right->red = 0;
/* left rotate p */
p->right = q->left;
q->left = p;
*pp = q;
}
/* We're done. */
sp = 1;
r = NULL;
}
}
else
{
/* Comments: see above. */
q = p->left;
if (q != NULL && q->red)
{
q->red = 0;
p->red = 1;
p->left = q->right;
q->right = p;
*pp = q;
nodestack[sp++] = pp = &q->right;
q = p->left;
}
if ((q->right == NULL || !q->right->red)
&& (q->left == NULL || !q->left->red))
{
q->red = 1;
r = p;
}
else
{
if (q->left == NULL || !q->left->red)
{
node q2 = q->right;
q2->red = p->red;
p->left = q2->right;
q->right = q2->left;
q2->left = q;
q2->right = p;
*pp = q2;
p->red = 0;
}
else
{
q->red = p->red;
p->red = 0;
q->left->red = 0;
p->left = q->right;
q->right = p;
*pp = q;
}
sp = 1;
r = NULL;
}
}
--sp;
}
if (r != NULL)
r->red = 0;
}
free (unchained);
return retval;
}
weak_alias (__tdelete, tdelete)
/* Walk the nodes of a tree
node *root; Root of the tree to be walked
void (*action)(); Function to be called at each node
int level;
*/
/* Walk the nodes of a tree.
ROOT is the root of the tree to be walked, ACTION the function to be
called at each node. LEVEL is the level of ROOT in the whole tree. */
static void
trecurse (vroot, action, level)
const void *vroot;
__action_fn_t action;
int level;
trecurse (const void *vroot, __action_fn_t action, int level)
{
node *root = (node *) vroot;
node root = (node ) vroot;
if (root->left == NULL && root->right == NULL)
(*action) (root, leaf, level);
@ -201,17 +611,15 @@ trecurse (vroot, action, level)
}
/* void twalk(root, action) Walk the nodes of a tree
node *root; Root of the tree to be walked
void (*action)(); Function to be called at each node
PTR
*/
/* Walk the nodes of a tree.
ROOT is the root of the tree to be walked, ACTION the function to be
called at each node. */
void
__twalk (vroot, action)
const void *vroot;
__action_fn_t action;
__twalk (const void *vroot, __action_fn_t action)
{
const node *root = (node *) vroot;
const node root = (node) vroot;
CHECK_TREE (root);
if (root != NULL && action != NULL)
trecurse (root, action, 0);

329
misc/tst-tsearch.c Normal file
View File

@ -0,0 +1,329 @@
/* Test program for tsearch et al.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <search.h>
#define SEED 0
#define BALANCED 1
#define PASSES 100
#if BALANCED
#include <math.h>
#define SIZE 1000
#else
#define SIZE 100
#endif
enum order
{
ascending,
descending,
randomorder
};
enum action
{
build,
build_and_del,
delete,
find
};
/* Set to 1 if a test is flunked. */
static int error = 0;
/* The keys we add to the tree. */
static int x[SIZE];
/* Pointers into the key array, possibly permutated, to define an order
for insertion/removal. */
static int y[SIZE];
/* Flags set for each element visited during a tree walk. */
static int z[SIZE];
/* Depths for all the elements, to check that the depth is constant for
all three visits. */
static int depths[SIZE];
/* Maximum depth during a tree walk. */
static int max_depth;
/* Compare two keys. */
static int
cmp_fn (const void *a, const void *b)
{
return *(const int *) a - *(const int *) b;
}
/* Permute an array of integers. */
static void
memfry (int *string)
{
int i;
for (i = 0; i < SIZE; ++i)
{
int32_t j;
int c;
j = random () % SIZE;
c = string[i];
string[i] = string[j];
string[j] = c;
}
}
static void
walk_action (const void *nodep, const VISIT which, const int depth)
{
int key = **(int **) nodep;
if (depth > max_depth)
max_depth = depth;
if (which == leaf || which == preorder)
{
++z[key];
depths[key] = depth;
}
else
{
if (depths[key] != depth)
{
fputs ("Depth for one element is not constant during tree walk.\n",
stderr);
}
}
}
static void
walk_tree (void *root, int expected_count)
{
int i;
memset (z, 0, sizeof z);
max_depth = 0;
twalk (root, walk_action);
for (i = 0; i < expected_count; ++i)
if (z[i] != 1)
{
fputs ("Node was not visited.\n", stderr);
error = 1;
}
#if BALANCED
if (max_depth > log (expected_count) * 2 + 2)
#else
if (max_depth > expected_count)
#endif
{
fputs ("Depth too large during tree walk.\n", stderr);
error = 1;
}
}
/* Perform an operation on a tree. */
static void
mangle_tree (enum order how, enum action what, void **root, int lag)
{
int i;
if (how == randomorder)
{
for (i = 0; i < SIZE; ++i)
y[i] = i;
memfry (y);
}
for (i = 0; i < SIZE + lag; ++i)
{
void *elem;
int j, k;
switch (how)
{
case randomorder:
if (i >= lag)
k = y[i - lag];
else
k = y[SIZE - i - 1 + lag];
j = y[i];
break;
case ascending:
k = i - lag;
j = i;
break;
case descending:
k = SIZE - i - 1 + lag;
j = SIZE - i - 1;
break;
default:
/* This never should happen, but gcc isn't smart enough to
recognize it. */
abort ();
}
switch (what)
{
case build_and_del:
case build:
if (i < SIZE)
{
if (tfind (x + j, (const void **) root, cmp_fn) != NULL)
{
fputs ("Found element which is not in tree yet.\n", stderr);
error = 1;
}
elem = tsearch (x + j, root, cmp_fn);
if (elem == 0
|| tfind (x + j, (const void **) root, cmp_fn) == NULL)
{
fputs ("Couldn't find element after it was added.\n",
stderr);
error = 1;
}
}
if (what == build || i < lag)
break;
j = k;
/* fall through */
case delete:
elem = tfind (x + j, (const void **) root, cmp_fn);
if (elem == NULL || tdelete (x + j, root, cmp_fn) == NULL)
{
fputs ("Error deleting element.\n", stderr);
error = 1;
}
break;
case find:
if (tfind (x + j, (const void **) root, cmp_fn) == NULL)
{
fputs ("Couldn't find element after it was added.\n", stderr);
error = 1;
}
break;
}
}
}
int
main (int argc, char **argv)
{
int total_error = 0;
static int state[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
void *root = NULL;
int i, j;
initstate (SEED, state, 8);
for (i = 0; i < SIZE; ++i)
x[i] = i;
/* Do this loop several times to get different permutations for the
random case. */
fputs ("Series I\n", stderr);
for (i = 0; i < PASSES; ++i)
{
fprintf (stderr, "Pass %d... ", i + 1);
fflush (stdout);
error = 0;
mangle_tree (ascending, build, &root, 0);
mangle_tree (ascending, find, &root, 0);
mangle_tree (descending, find, &root, 0);
mangle_tree (randomorder, find, &root, 0);
walk_tree (root, SIZE);
mangle_tree (ascending, delete, &root, 0);
mangle_tree (ascending, build, &root, 0);
walk_tree (root, SIZE);
mangle_tree (descending, delete, &root, 0);
mangle_tree (ascending, build, &root, 0);
walk_tree (root, SIZE);
mangle_tree (randomorder, delete, &root, 0);
mangle_tree (descending, build, &root, 0);
mangle_tree (ascending, find, &root, 0);
mangle_tree (descending, find, &root, 0);
mangle_tree (randomorder, find, &root, 0);
walk_tree (root, SIZE);
mangle_tree (descending, delete, &root, 0);
mangle_tree (descending, build, &root, 0);
walk_tree (root, SIZE);
mangle_tree (descending, delete, &root, 0);
mangle_tree (descending, build, &root, 0);
walk_tree (root, SIZE);
mangle_tree (randomorder, delete, &root, 0);
mangle_tree (randomorder, build, &root, 0);
mangle_tree (ascending, find, &root, 0);
mangle_tree (descending, find, &root, 0);
mangle_tree (randomorder, find, &root, 0);
walk_tree (root, SIZE);
mangle_tree (randomorder, delete, &root, 0);
for (j = 1; j < SIZE; j *= 2)
{
mangle_tree (randomorder, build_and_del, &root, j);
}
fputs (error ? " failed!\n" : " ok.\n", stderr);
total_error |= error;
}
fputs ("Series II\n", stderr);
for (i = 1; i < SIZE; i *= 2)
{
fprintf (stderr, "For size %d... ", i);
fflush (stdout);
error = 0;
mangle_tree (ascending, build_and_del, &root, i);
mangle_tree (descending, build_and_del, &root, i);
mangle_tree (ascending, build_and_del, &root, i);
mangle_tree (descending, build_and_del, &root, i);
mangle_tree (ascending, build_and_del, &root, i);
mangle_tree (descending, build_and_del, &root, i);
mangle_tree (ascending, build_and_del, &root, i);
mangle_tree (descending, build_and_del, &root, i);
fputs (error ? " failed!\n" : " ok.\n", stderr);
total_error |= error;
}
return total_error;
}

View File

@ -241,13 +241,13 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
static int
nss_dlerror_run (void (*operate) (void))
nss_dlerror_run (void (*operate) (void *), void *args)
{
char *last_errstring = NULL;
const char *last_object_name = NULL;
int result;
(void) _dl_catch_error (&last_errstring, &last_object_name, operate);
(void) _dl_catch_error (&last_errstring, &last_object_name, operate, args);
result = last_errstring != NULL;
if (result)
@ -257,6 +257,42 @@ nss_dlerror_run (void (*operate) (void))
}
struct do_open_args
{
/* Argument to do_open. */
char *shlib_name;
service_user *ni;
};
struct get_sym_args
{
/* Arguments to get_sym. */
struct link_map *map;
char *name;
/* Return values of get_sym. */
ElfW(Addr) loadbase;
const ElfW(Sym) *ref;
};
static void
do_open (void *a)
{
struct do_open_args *args = (struct do_open_args *) a;
/* Open and relocate the shared object. */
args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY);
}
static void
get_sym (void *a)
{
struct get_sym_args *args = (struct get_sym_args *) a;
struct link_map *scope[2] = { args->map, NULL };
args->ref = NULL;
args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
scope, args->map->l_name, 0);
}
/* Comparison function for searching NI->known tree. */
static int
known_compare (const void *p1, const void *p2)
@ -332,21 +368,19 @@ nss_lookup_function (service_user *ni, const char *fct_name)
/* Load the shared library. */
size_t shlen = (7 + strlen (ni->library->name) + 3
+ strlen (__nss_shlib_revision) + 1);
char shlib_name[shlen];
void do_open (void)
{
/* Open and relocate the shared object. */
ni->library->lib_handle = _dl_open (shlib_name, RTLD_LAZY);
}
struct do_open_args args;
args.shlib_name = __alloca (shlen);
args.ni = ni;
/* Construct shared object name. */
__stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name, "libnss_"),
__stpcpy (__stpcpy (__stpcpy (__stpcpy (args.shlib_name,
"libnss_"),
ni->library->name),
".so"),
__nss_shlib_revision);
if (nss_dlerror_run (do_open) != 0)
if (nss_dlerror_run (do_open, &args) != 0)
/* Failed to load the library. */
ni->library->lib_handle = (void *) -1l;
}
@ -359,26 +393,19 @@ nss_lookup_function (service_user *ni, const char *fct_name)
/* Get the desired function. Again, GNU ld.so magic ahead. */
size_t namlen = (5 + strlen (ni->library->name) + 1
+ strlen (fct_name) + 1);
char name[namlen];
struct link_map *map = ni->library->lib_handle;
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
void get_sym (void)
{
struct link_map *scope[2] = { map, NULL };
loadbase = _dl_lookup_symbol (name, &ref,
scope, map->l_name, 0);
}
struct get_sym_args args;
args.name = __alloca (namlen);
args.map = ni->library->lib_handle;
/* Construct the function name. */
__stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"),
__stpcpy (__stpcpy (__stpcpy (__stpcpy (args.name, "_nss_"),
ni->library->name),
"_"),
fct_name);
/* Look up the symbol. */
result = (nss_dlerror_run (get_sym)
? NULL : (void *) (loadbase + ref->st_value));
result = (nss_dlerror_run (get_sym, &args) ? NULL
: (void *) (args.loadbase + args.ref->st_value));
}
/* Remember function pointer for later calls. Even if null, we

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,10 @@ main (void)
puts ("There should be no further output from this test.");
fflush (stdout);
/* We must remove this entry to assure the `cmp' binary does not use
the perhaps incompatible new shared libraries. */
unsetenv ("LD_LIBRARY_PATH");
asprintf (&printbuf, "cmp %s %s", inname, outname);
result = system (printbuf);
remove (inname);

View File

@ -1,9 +1,27 @@
#include <ansidecl.h>
/* Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
void
DEFUN(write_data, (stream), FILE *stream)
write_data (FILE *stream)
{
int i;
for (i=0; i<100; i++)
@ -15,7 +33,7 @@ DEFUN(write_data, (stream), FILE *stream)
}
void
DEFUN(read_data, (stream), FILE *stream)
read_data (FILE *stream)
{
int i, j;
@ -32,11 +50,15 @@ DEFUN(read_data, (stream), FILE *stream)
}
int
DEFUN_VOID(main)
main (void)
{
FILE *output, *input;
int wstatus, rstatus;
/* We must remove this entry to assure the `cat' binary does not use
the perhaps incompatible new shared libraries. */
unsetenv ("LD_LIBRARY_PATH");
output = popen ("/bin/cat >/tmp/tstpopen.tmp", "w");
if (output == NULL)
{

248
sysdeps/libm-i387/s_cexp.S Normal file
View File

@ -0,0 +1,248 @@
/* ix87 specific implementation of complex exponential function for double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <sysdep.h>
#ifdef __ELF__
.section .rodata
#else
.text
#endif
.align ALIGNARG(4)
ASM_TYPE_DIRECTIVE(huge_nan_null_null,@object)
huge_nan_null_null:
.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
.double 0.0
.double 0.0
.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
.double 0.0
.byte 0, 0, 0, 0, 0, 0, 0, 0x80
ASM_SIZE_DIRECTIVE(huge_nan_null_null)
ASM_TYPE_DIRECTIVE(twopi,@object)
twopi:
.byte 0x35, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0xf, 0xc9, 0x1, 0x40
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(twopi)
ASM_TYPE_DIRECTIVE(l2e,@object)
l2e:
.byte 0xbc, 0xf0, 0x17, 0x5c, 0x29, 0x3b, 0xaa, 0xb8, 0xff, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(l2e)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
#ifdef PIC
#define MO(op) op##@GOTOFF(%ecx)
#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
#else
#define MO(op) op
#define MOX(op,x,f) op(,x,f)
#endif
.text
ENTRY(__cexp)
fldl 8(%esp) /* x */
fxam
fnstsw
fldl 16(%esp) /* y : x */
#ifdef PIC
call 1f
1: popl %ecx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
#endif
movb %ah, %dh
andb $0x45, %ah
cmpb $0x05, %ah
je 1f /* Jump if real part is +-Inf */
cmpb $0x01, %ah
je 2f /* Jump if real part is NaN */
fxam /* y : x */
fnstsw
/* If the imaginary part is not finite we return NaN+i NaN, as
for the case when the real part is NaN. A test for +-Inf and
NaN would be necessary. But since we know the stack register
we applied `fxam' to is not empty we can simply use one test.
Check your FPU manual for more information. */
andb $0x01, %ah
cmpb $0x01, %ah
je 2f
/* We have finite numbers in the real and imaginary part. Do
the real work now. */
fxch /* x : y */
fldt MO(l2e) /* log2(e) : x : y */
fmulp /* x * log2(e) : y */
fld %st /* x * log2(e) : x * log2(e) : y */
frndint /* int(x * log2(e)) : x * log2(e) : y */
fsubr %st, %st(1) /* int(x * log2(e)) : frac(x * log2(e)) : y */
fxch /* frac(x * log2(e)) : int(x * log2(e)) : y */
f2xm1 /* 2^frac(x * log2(e))-1 : int(x * log2(e)) : y */
faddl MO(one) /* 2^frac(x * log2(e)) : int(x * log2(e)) : y */
fscale /* e^x : int(x * log2(e)) : y */
fst %st(1) /* e^x : e^x : y */
fxch %st(2) /* y : e^x : e^x */
fsincos /* cos(y) : sin(y) : e^x : e^x */
fnstsw
testl $0x400, %eax
jnz 7f
fmulp %st, %st(3) /* sin(y) : e^x : e^x * cos(y) */
fmulp %st, %st(1) /* e^x * sin(y) : e^x * cos(y) */
movl 4(%esp), %eax /* Pointer to memory for result. */
fstpl 8(%eax)
fstpl (%eax)
ret $4
/* We have to reduce the argument to fsincos. */
.align ALIGNARG(4)
7: fldt MO(twopi) /* 2*pi : y : e^x : e^x */
fxch /* y : 2*pi : e^x : e^x */
8: fprem1 /* y%(2*pi) : 2*pi : e^x : e^x */
fnstsw
testl $0x400, %eax
jnz 8b
fstp %st(1) /* y%(2*pi) : e^x : e^x */
fsincos /* cos(y) : sin(y) : e^x : e^x */
fmulp %st, %st(3)
fmulp %st, %st(1)
movl 4(%esp), %eax /* Pointer to memory for result. */
fstpl 8(%eax)
fstpl (%eax)
ret $4
/* The real part is +-inf. We must make further differences. */
.align ALIGNARG(4)
1: fxam /* y : x */
fnstsw
movb %ah, %dl
andb $0x01, %ah /* See above why 0x01 is usable here. */
cmpb $0x01, %ah
je 3f
/* The real part is +-Inf and the imaginary part is finite. */
andl $0x245, %edx
cmpb $0x40, %dl /* Imaginary part == 0? */
je 4f /* Yes -> */
fxch /* x : y */
shrl $5, %edx
fstp %st(0) /* y */ /* Drop the real part. */
andl $16, %edx /* This puts the sign bit of the real part
in bit 4. So we can use it to index a
small array to select 0 or Inf. */
fsincos /* cos(y) : sin(y) */
fnstsw
testl $0x0400, %eax
jnz 5f
fldl MOX(huge_nan_null_null,%edx,1)
movl 4(%esp), %edx /* Pointer to memory for result. */
fstl 8(%edx)
fstpl (%edx)
ftst
fnstsw
shll $23, %eax
andl $0x80000000, %eax
orl %eax, 4(%edx)
fstp %st(0)
ftst
fnstsw
shll $23, %eax
andl $0x80000000, %eax
orl %eax, 12(%edx)
fstp %st(0)
ret $4
/* We must reduce the argument to fsincos. */
.align ALIGNARG(4)
5: fldt MO(twopi)
fxch
6: fprem1
fnstsw
testl $0x400, %eax
jnz 6b
fstp %st(1)
fsincos
fldl MOX(huge_nan_null_null,%edx,1)
movl 4(%esp), %edx /* Pointer to memory for result. */
fstl 8(%edx)
fstpl (%edx)
ftst
fnstsw
shll $23, %eax
andl $0x80000000, %eax
orl %eax, 4(%edx)
fstp %st(0)
ftst
fnstsw
shll $23, %eax
andl $0x80000000, %eax
orl %eax, 12(%edx)
fstp %st(0)
ret $4
/* The real part is +-Inf and the imaginary part is +-0. So return
+-Inf+-0i. */
.align ALIGNARG(4)
4: movl 4(%esp), %eax /* Pointer to memory for result. */
fstpl 8(%eax)
shrl $5, %edx
fstp %st(0)
andl $16, %edx
fldl MOX(huge_nan_null_null,%edx,1)
fstpl (%eax)
ret $4
/* The real part is +-Inf, the imaginary is also is not finite. */
.align ALIGNARG(4)
3: fstp %st(0)
fstp %st(0) /* <empty> */
movl %edx, %eax
shrl $5, %edx
shll $4, %eax
andl $16, %edx
andl $32, %eax
orl %eax, %edx
movl 4(%esp), %eax /* Pointer to memory for result. */
fldl MOX(huge_nan_null_null,%edx,1)
fldl MOX(huge_nan_null_null+8,%edx,1)
fstpl 8(%eax)
fstpl (%eax)
ret $4
/* The real part is NaN. */
.align ALIGNARG(4)
2: fstp %st(0)
fstp %st(0)
movl 4(%esp), %eax /* Pointer to memory for result. */
fldl MO(huge_nan_null_null+8)
fstl (%eax)
fstpl 8(%eax)
ret $4
END(__cexp)
weak_alias (__cexp, cexp)

245
sysdeps/libm-i387/s_cexpf.S Normal file
View File

@ -0,0 +1,245 @@
/* ix87 specific implementation of complex exponential function for double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <sysdep.h>
#ifdef __ELF__
.section .rodata
#else
.text
#endif
.align ALIGNARG(4)
ASM_TYPE_DIRECTIVE(huge_nan_null_null,@object)
huge_nan_null_null:
.byte 0, 0, 0x80, 0x7f
.byte 0, 0, 0xc0, 0x7f
.float 0.0
.float 0.0
.byte 0, 0, 0x80, 0x7f
.byte 0, 0, 0xc0, 0x7f
.float 0.0
.byte 0, 0, 0, 0x80
ASM_SIZE_DIRECTIVE(huge_nan_null_null)
ASM_TYPE_DIRECTIVE(twopi,@object)
twopi:
.byte 0x35, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0xf, 0xc9, 0x1, 0x40
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(twopi)
ASM_TYPE_DIRECTIVE(l2e,@object)
l2e:
.byte 0xbc, 0xf0, 0x17, 0x5c, 0x29, 0x3b, 0xaa, 0xb8, 0xff, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(l2e)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
#ifdef PIC
#define MO(op) op##@GOTOFF(%ecx)
#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
#else
#define MO(op) op
#define MOX(op,x,f) op(,x,f)
#endif
.text
ENTRY(__cexpf)
flds 4(%esp) /* x */
fxam
fnstsw
flds 8(%esp) /* y : x */
#ifdef PIC
call 1f
1: popl %ecx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
#endif
movb %ah, %dh
andb $0x45, %ah
cmpb $0x05, %ah
je 1f /* Jump if real part is +-Inf */
cmpb $0x01, %ah
je 2f /* Jump if real part is NaN */
fxam /* y : x */
fnstsw
/* If the imaginary part is not finite we return NaN+i NaN, as
for the case when the real part is NaN. A test for +-Inf and
NaN would be necessary. But since we know the stack register
we applied `fxam' to is not empty we can simply use one test.
Check your FPU manual for more information. */
andb $0x01, %ah
cmpb $0x01, %ah
je 2f
/* We have finite numbers in the real and imaginary part. Do
the real work now. */
fxch /* x : y */
fldt MO(l2e) /* log2(e) : x : y */
fmulp /* x * log2(e) : y */
fld %st /* x * log2(e) : x * log2(e) : y */
frndint /* int(x * log2(e)) : x * log2(e) : y */
fsubr %st, %st(1) /* int(x * log2(e)) : frac(x * log2(e)) : y */
fxch /* frac(x * log2(e)) : int(x * log2(e)) : y */
f2xm1 /* 2^frac(x * log2(e))-1 : int(x * log2(e)) : y */
faddl MO(one) /* 2^frac(x * log2(e)) : int(x * log2(e)) : y */
fscale /* e^x : int(x * log2(e)) : y */
fst %st(1) /* e^x : e^x : y */
fxch %st(2) /* y : e^x : e^x */
fsincos /* cos(y) : sin(y) : e^x : e^x */
fnstsw
testl $0x400, %eax
jnz 7f
fmulp %st, %st(3) /* sin(y) : e^x : e^x * cos(y) */
fmulp %st, %st(1) /* e^x * sin(y) : e^x * cos(y) */
subl $8, %esp
fstps 4(%esp)
fstps (%esp)
popl %eax
popl %edx
ret
/* We have to reduce the argument to fsincos. */
.align ALIGNARG(4)
7: fldt MO(twopi) /* 2*pi : y : e^x : e^x */
fxch /* y : 2*pi : e^x : e^x */
8: fprem1 /* y%(2*pi) : 2*pi : e^x : e^x */
fnstsw
testl $0x400, %eax
jnz 8b
fstp %st(1) /* y%(2*pi) : e^x : e^x */
fsincos /* cos(y) : sin(y) : e^x : e^x */
fmulp %st, %st(3)
fmulp %st, %st(1)
subl $8, %esp
fstps 4(%esp)
fstps (%esp)
popl %eax
popl %edx
ret
/* The real part is +-inf. We must make further differences. */
.align ALIGNARG(4)
1: fxam /* y : x */
fnstsw
movb %ah, %dl
andb $0x01, %ah /* See above why 0x01 is usable here. */
cmpb $0x01, %ah
je 3f
/* The real part is +-Inf and the imaginary part is finite. */
andl $0x245, %edx
cmpb $0x40, %dl /* Imaginary part == 0? */
je 4f /* Yes -> */
fxch /* x : y */
shrl $6, %edx
fstp %st(0) /* y */ /* Drop the real part. */
andl $8, %edx /* This puts the sign bit of the real part
in bit 3. So we can use it to index a
small array to select 0 or Inf. */
fsincos /* cos(y) : sin(y) */
fnstsw
testl $0x0400, %eax
jnz 5f
fxch
ftst
fnstsw
fstp %st(0)
shll $23, %eax
andl $0x80000000, %eax
orl MOX(huge_nan_null_null,%edx,1), %eax
movl MOX(huge_nan_null_null,%edx,1), %ecx
movl %eax, %edx
ftst
fnstsw
fstp %st(0)
shll $23, %eax
andl $0x80000000, %eax
orl %ecx, %eax
ret
/* We must reduce the argument to fsincos. */
.align ALIGNARG(4)
5: fldt MO(twopi)
fxch
6: fprem1
fnstsw
testl $0x400, %eax
jnz 6b
fstp %st(1)
fsincos
fxch
ftst
fnstsw
fstp %st(0)
shll $23, %eax
andl $0x80000000, %eax
orl MOX(huge_nan_null_null,%edx,1), %eax
movl MOX(huge_nan_null_null,%edx,1), %ecx
movl %eax, %edx
ftst
fnstsw
fstp %st(0)
shll $23, %eax
andl $0x80000000, %eax
orl %ecx, %eax
ret
/* The real part is +-Inf and the imaginary part is +-0. So return
+-Inf+-0i. */
.align ALIGNARG(4)
4: subl $4, %esp
fstps (%esp)
shrl $6, %edx
fstp %st(0)
andl $8, %edx
movl MOX(huge_nan_null_null,%edx,1), %eax
popl %edx
ret
/* The real part is +-Inf, the imaginary is also is not finite. */
.align ALIGNARG(4)
3: fstp %st(0)
fstp %st(0) /* <empty> */
movl %edx, %eax
shrl $6, %edx
shll $3, %eax
andl $8, %edx
andl $16, %eax
orl %eax, %edx
movl MOX(huge_nan_null_null,%edx,1), %eax
movl MOX(huge_nan_null_null+4,%edx,1), %edx
ret
/* The real part is NaN. */
.align ALIGNARG(4)
2: fstp %st(0)
fstp %st(0)
movl MO(huge_nan_null_null+4), %eax
movl %eax, %edx
ret
END(__cexpf)
weak_alias (__cexpf, cexpf)

249
sysdeps/libm-i387/s_cexpl.S Normal file
View File

@ -0,0 +1,249 @@
/* ix87 specific implementation of complex exponential function for double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <sysdep.h>
#ifdef __ELF__
.section .rodata
#else
.text
#endif
.align ALIGNARG(4)
ASM_TYPE_DIRECTIVE(huge_nan_null_null,@object)
huge_nan_null_null:
.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
.double 0.0
.double 0.0
.byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
.double 0.0
.byte 0, 0, 0, 0, 0, 0, 0, 0x80
ASM_SIZE_DIRECTIVE(huge_nan_null_null)
ASM_TYPE_DIRECTIVE(twopi,@object)
twopi:
.byte 0x35, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0xf, 0xc9, 0x1, 0x40
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(twopi)
ASM_TYPE_DIRECTIVE(l2e,@object)
l2e:
.byte 0xbc, 0xf0, 0x17, 0x5c, 0x29, 0x3b, 0xaa, 0xb8, 0xff, 0x3f
.byte 0, 0, 0, 0, 0, 0
ASM_SIZE_DIRECTIVE(l2e)
ASM_TYPE_DIRECTIVE(one,@object)
one: .double 1.0
ASM_SIZE_DIRECTIVE(one)
#ifdef PIC
#define MO(op) op##@GOTOFF(%ecx)
#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
#else
#define MO(op) op
#define MOX(op,x,f) op(,x,f)
#endif
.text
ENTRY(__cexpl)
fldt 8(%esp) /* x */
fxam
fnstsw
fldt 20(%esp) /* y : x */
#ifdef PIC
call 1f
1: popl %ecx
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
#endif
movb %ah, %dh
andb $0x45, %ah
cmpb $0x05, %ah
je 1f /* Jump if real part is +-Inf */
cmpb $0x01, %ah
je 2f /* Jump if real part is NaN */
fxam /* y : x */
fnstsw
/* If the imaginary part is not finite we return NaN+i NaN, as
for the case when the real part is NaN. A test for +-Inf and
NaN would be necessary. But since we know the stack register
we applied `fxam' to is not empty we can simply use one test.
Check your FPU manual for more information. */
andb $0x01, %ah
cmpb $0x01, %ah
je 2f
/* We have finite numbers in the real and imaginary part. Do
the real work now. */
fxch /* x : y */
fldt MO(l2e) /* log2(e) : x : y */
fmulp /* x * log2(e) : y */
fld %st /* x * log2(e) : x * log2(e) : y */
frndint /* int(x * log2(e)) : x * log2(e) : y */
fsubr %st, %st(1) /* int(x * log2(e)) : frac(x * log2(e)) : y */
fxch /* frac(x * log2(e)) : int(x * log2(e)) : y */
f2xm1 /* 2^frac(x * log2(e))-1 : int(x * log2(e)) : y */
faddl MO(one) /* 2^frac(x * log2(e)) : int(x * log2(e)) : y */
fscale /* e^x : int(x * log2(e)) : y */
fst %st(1) /* e^x : e^x : y */
fxch %st(2) /* y : e^x : e^x */
fsincos /* cos(y) : sin(y) : e^x : e^x */
fnstsw
testl $0x400, %eax
jnz 7f
fmulp %st, %st(3) /* sin(y) : e^x : e^x * cos(y) */
fmulp %st, %st(1) /* e^x * sin(y) : e^x * cos(y) */
movl 4(%esp), %eax /* Pointer to memory for result. */
fstpt 12(%eax)
fstpt (%eax)
ret $4
/* We have to reduce the argument to fsincos. */
.align ALIGNARG(4)
7: fldt MO(twopi) /* 2*pi : y : e^x : e^x */
fxch /* y : 2*pi : e^x : e^x */
8: fprem1 /* y%(2*pi) : 2*pi : e^x : e^x */
fnstsw
testl $0x400, %eax
jnz 8b
fstp %st(1) /* y%(2*pi) : e^x : e^x */
fsincos /* cos(y) : sin(y) : e^x : e^x */
fmulp %st, %st(3)
fmulp %st, %st(1)
movl 4(%esp), %eax /* Pointer to memory for result. */
fstpt 12(%eax)
fstpt (%eax)
ret $4
/* The real part is +-inf. We must make further differences. */
.align ALIGNARG(4)
1: fxam /* y : x */
fnstsw
movb %ah, %dl
andb $0x01, %ah /* See above why 0x01 is usable here. */
cmpb $0x01, %ah
je 3f
/* The real part is +-Inf and the imaginary part is finite. */
andl $0x245, %edx
cmpb $0x40, %dl /* Imaginary part == 0? */
je 4f /* Yes -> */
fxch /* x : y */
shrl $5, %edx
fstp %st(0) /* y */ /* Drop the real part. */
andl $16, %edx /* This puts the sign bit of the real part
in bit 4. So we can use it to index a
small array to select 0 or Inf. */
fsincos /* cos(y) : sin(y) */
fnstsw
testl $0x0400, %eax
jnz 5f
fldl MOX(huge_nan_null_null,%edx,1)
movl 4(%esp), %edx /* Pointer to memory for result. */
fstl 8(%edx)
fstpl (%edx)
ftst
fnstsw
shll $7, %eax
andl $0x8000, %eax
orl %eax, 8(%edx)
fstp %st(0)
ftst
fnstsw
shll $7, %eax
andl $0x8000, %eax
orl %eax, 20(%edx)
fstp %st(0)
ret $4
/* We must reduce the argument to fsincos. */
.align ALIGNARG(4)
5: fldt MO(twopi)
fxch
6: fprem1
fnstsw
testl $0x400, %eax
jnz 6b
fstp %st(1)
fsincos
fldl MOX(huge_nan_null_null,%edx,1)
movl 4(%esp), %edx /* Pointer to memory for result. */
fstl 8(%edx)
fstpl (%edx)
ftst
fnstsw
shll $7, %eax
andl $0x8000, %eax
orl %eax, 8(%edx)
fstp %st(0)
ftst
fnstsw
shll $7, %eax
andl $0x8000, %eax
orl %eax, 20(%edx)
fstp %st(0)
ret $4
/* The real part is +-Inf and the imaginary part is +-0. So return
+-Inf+-0i. */
.align ALIGNARG(4)
4: movl 4(%esp), %eax /* Pointer to memory for result. */
fstpt 12(%eax)
shrl $5, %edx
fstp %st(0)
andl $16, %edx
fldl MOX(huge_nan_null_null,%edx,1)
fstpt (%eax)
ret $4
/* The real part is +-Inf, the imaginary is also is not finite. */
.align ALIGNARG(4)
3: fstp %st(0)
fstp %st(0) /* <empty> */
movl %edx, %eax
shrl $5, %edx
shll $4, %eax
andl $16, %edx
andl $32, %eax
orl %eax, %edx
movl 4(%esp), %eax /* Pointer to memory for result. */
fldl MOX(huge_nan_null_null,%edx,1)
fldl MOX(huge_nan_null_null+8,%edx,1)
fstpt 12(%eax)
fstpt (%eax)
ret $4
/* The real part is NaN. */
.align ALIGNARG(4)
2: fstp %st(0)
fstp %st(0)
movl 4(%esp), %eax /* Pointer to memory for result. */
fldl MO(huge_nan_null_null+8)
fld %st(0)
fstpt (%eax)
fstpt 12(%eax)
ret $4
END(__cexpl)
weak_alias (__cexpl, cexpl)

View File

@ -0,0 +1,95 @@
/* Complex cosine hyperbole function for double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
__complex__ double
__ccosh (__complex__ double x)
{
__complex__ double retval;
__real__ x = fabs (__real__ x);
if (isfinite (__real__ x))
{
if (isfinite (__imag__ x))
{
double exp_val = __exp (__real__ x);
double rec_exp_val = 1.0 / exp_val;
__real__ retval = 0.5 * (exp_val + rec_exp_val) * __cos (__imag__ x);
__imag__ retval = 0.5 * (exp_val + rec_exp_val) * __sin (__imag__ x);
}
else
{
if (__real__ x == 0)
{
__imag__ retval = 0.0;
__real__ retval = __nan ("") + __nan ("");
}
else
{
__real__ retval = __nan ("");
__imag__ retval = __nan ("") + __nan ("");
}
}
}
else if (__isinf (__real__ x))
{
if (__imag__ x == 0.0)
{
__real__ retval = HUGE_VAL;
__imag__ retval = __imag__ x;
}
else if (isfinite (__imag__ x))
{
__real__ retval = __copysign (HUGE_VAL, __cos (__imag__ x));
__imag__ retval = __copysign (HUGE_VAL, __sin (__imag__ x));
}
else
{
/* The addition raises the invalid exception. */
__real__ retval = HUGE_VAL;
__imag__ retval = __nan ("") + __nan ("");
}
}
else
{
if (__imag__ x == 0.0)
{
__real__ retval = __nan ("");
__imag__ retval = __imag__ x;
}
else
{
__real__ retval = __nan ("");
__imag__ retval = __nan ("");
}
}
return retval;
}
weak_alias (__ccosh, ccosh)
#ifdef NO_LONG_DOUBLE
strong_alias (__ccosh, __ccoshl)
weak_alias (__ccosh, ccoshl)
#endif

View File

@ -0,0 +1,93 @@
/* Complex cosine hyperbole function for float.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
__complex__ float
__ccoshf (__complex__ float x)
{
__complex__ float retval;
__real__ x = fabsf (__real__ x);
if (isfinite (__real__ x))
{
if (isfinite (__imag__ x))
{
float exp_val = __expf (__real__ x);
float rec_exp_val = 1.0 / exp_val;
__real__ retval = (0.5 * (exp_val + rec_exp_val)
* __cosf (__imag__ x));
__imag__ retval = (0.5 * (exp_val + rec_exp_val)
* __sinf (__imag__ x));
}
else
{
if (__real__ x == 0)
{
__imag__ retval = 0.0;
__real__ retval = __nanf ("") + __nanf ("");
}
else
{
__real__ retval = __nanf ("");
__imag__ retval = __nanf ("") + __nanf ("");
}
}
}
else if (__isinff (__real__ x))
{
if (__imag__ x == 0.0)
{
__real__ retval = HUGE_VALF;
__imag__ retval = __imag__ x;
}
else if (isfinite (__imag__ x))
{
__real__ retval = __copysignf (HUGE_VALF, __cosf (__imag__ x));
__imag__ retval = __copysignf (HUGE_VALF, __sinf (__imag__ x));
}
else
{
/* The addition raises the invalid exception. */
__real__ retval = HUGE_VALF;
__imag__ retval = __nanf ("") + __nanf ("");
}
}
else
{
if (__imag__ x == 0.0)
{
__real__ retval = __nanf ("");
__imag__ retval = __imag__ x;
}
else
{
__real__ retval = __nanf ("");
__imag__ retval = __nanf ("");
}
}
return retval;
}
weak_alias (__ccoshf, ccoshf)

View File

@ -0,0 +1,93 @@
/* Complex cosine hyperbole function for long double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
__complex__ long double
__ccoshl (__complex__ long double x)
{
__complex__ long double retval;
__real__ x = fabsl (__real__ x);
if (isfinite (__real__ x))
{
if (isfinite (__imag__ x))
{
long double exp_val = __expl (__real__ x);
long double rec_exp_val = 1.0 / exp_val;
__real__ retval = (0.5 * (exp_val + rec_exp_val)
* __cosl (__imag__ x));
__imag__ retval = (0.5 * (exp_val + rec_exp_val)
* __sinl (__imag__ x));
}
else
{
if (__real__ x == 0)
{
__imag__ retval = 0.0;
__real__ retval = __nanl ("") + __nanl ("");
}
else
{
__real__ retval = __nanl ("");
__imag__ retval = __nanl ("") + __nanl ("");
}
}
}
else if (__isinfl (__real__ x))
{
if (__imag__ x == 0.0)
{
__real__ retval = HUGE_VALL;
__imag__ retval = __imag__ x;
}
else if (isfinite (__imag__ x))
{
__real__ retval = __copysignl (HUGE_VALL, __cosl (__imag__ x));
__imag__ retval = __copysignl (HUGE_VALL, __sinl (__imag__ x));
}
else
{
/* The addition raises the invalid exception. */
__real__ retval = HUGE_VALL;
__imag__ retval = __nanl ("") + __nanl ("");
}
}
else
{
if (__imag__ x == 0.0)
{
__real__ retval = __nanl ("");
__imag__ retval = __imag__ x;
}
else
{
__real__ retval = __nanl ("");
__imag__ retval = __nanl ("");
}
}
return retval;
}
weak_alias (__ccoshl, ccoshl)

View File

@ -1,4 +1,4 @@
/* Return value of complex exponential function for double complex value.
/* Return value of complex exponential function for float complex value.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@ -31,33 +31,52 @@ __cexp (__complex__ double x)
{
if (isfinite (__imag__ x))
{
retval = __exp (__real__ x) * (__cos (__imag__ x)
+ 1i * __sin (__imag__ x));
double exp_val = __exp (__real__ x);
__real__ retval = exp_val * __cos (__imag__ x);
__imag__ retval = exp_val * __sin (__imag__ x);
}
else
/* If the imaginary part is +-inf or NaN and the real part is
not +-inf the result is NaN + iNan. */
retval = __nan ("") + 1.0i * __nan ("");
{
/* If the imaginary part is +-inf or NaN and the real part
is not +-inf the result is NaN + iNaN. */
__real__ retval = __nan ("");
__imag__ retval = __nan ("");
}
}
else if (__isinf (__real__ x))
{
if (isfinite (__imag x))
if (isfinite (__imag__ x))
{
if (signbit (__real__ x) == 0 && __imag__ x == 0.0)
retval = HUGE_VAL;
else
retval = ((signbit (__real__ x) ? 0.0 : HUGE_VAL)
* (__cos (__imag__ x) + 1i * __sin (__imag__ x)));
{
double value = signbit (__real__ x) ? 0.0 : HUGE_VAL;
__real__ retval = value * __cos (__imag__ x);
__imag__ retval = value * __sin (__imag__ x);
}
}
else if (signbit (__real__ x) == 0)
{
__real__ retval = HUGE_VAL;
__imag__ retval = __nan ("");
}
else if (signbit (__real__ x))
retval = HUGE_VAL + 1.0i * __nan ("");
else
retval = 0.0;
}
else
/* If the real part is NaN the result is NaN + iNan. */
retval = __nan ("") + 1.0i * __nan ("");
{
/* If the real part is NaN the result is NaN + iNaN. */
__real__ retval = __nan ("");
__imag__ retval = __nan ("");
}
return retval;
}
weak_alias (__cexp, cexp)
#ifdef NO_LONG_DOUBLE
string_alias (__cexp, __cexpl)
weak_alias (__cexp, cexpl)
#endif

View File

@ -33,8 +33,16 @@ __cexpf (__complex__ float x)
{
float exp_val = __expf (__real__ x);
__real__ retval = exp_val * __cosf (__imag__ x);
__imag__ retval = exp_val * __sinf (__imag__ x);
if (isfinite (exp_val))
{
__real__ retval = exp_val * __cosf (__imag__ x);
__imag__ retval = exp_val * __sinf (__imag__ x);
}
else
{
__real__ retval = __copysignf (exp_val, __cosf (__imag__ x));
__imag__ retval = __copysignf (exp_val, __sinf (__imag__ x));
}
}
else
{
@ -48,14 +56,17 @@ __cexpf (__complex__ float x)
{
if (isfinite (__imag__ x))
{
if (signbit (__real__ x) == 0 && __imag__ x == 0.0)
retval = HUGE_VALF;
float value = signbit (__real__ x) ? 0.0 : HUGE_VALF;
if (__imag__ x == 0.0)
{
__real__ retval = value;
__imag__ retval = __imag__ x;
}
else
{
float value = signbit (__real__ x) ? 0.0 : HUGE_VALF;
__real__ retval = value * __cosf (__imag__ x);
__imag__ retval = value * __sinf (__imag__ x);
__real__ retval = __copysignf (value, __cosf (__imag__ x));
__imag__ retval = __copysignf (value, __sinf (__imag__ x));
}
}
else if (signbit (__real__ x) == 0)
@ -64,7 +75,10 @@ __cexpf (__complex__ float x)
__imag__ retval = __nanf ("");
}
else
retval = 0.0;
{
__real__ retval = 0.0;
__imag__ retval = __copysignf (0.0, __imag__ x);
}
}
else
{

View File

@ -33,8 +33,16 @@ __cexpl (__complex__ long double x)
{
long double exp_val = __expl (__real__ x);
__real__ retval = exp_val * __cosl (__imag__ x);
__imag__ retval = exp_val * __sinl (__imag__ x);
if (isfinite (exp_val))
{
__real__ retval = exp_val * __cosl (__imag__ x);
__imag__ retval = exp_val * __sinl (__imag__ x);
}
else
{
__real__ retval = __copysignl (exp_val, __cosl (__imag__ x));
__imag__ retval = __copysignl (exp_val, __sinl (__imag__ x));
}
}
else
{
@ -48,14 +56,17 @@ __cexpl (__complex__ long double x)
{
if (isfinite (__imag__ x))
{
if (signbit (__real__ x) == 0 && __imag__ x == 0.0)
retval = HUGE_VAL;
long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;
if (__imag__ x == 0.0)
{
__real__ retval = value;
__imag__ retval = __imag__ x;
}
else
{
long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;
__real__ retval = value * __cosl (__imag__ x);
__imag__ retval = value * __sinl (__imag__ x);
__real__ retval = __copysignl (value, __cosl (__imag__ x));
__imag__ retval = __copysignl (value, __sinl (__imag__ x));
}
}
else if (signbit (__real__ x) == 0)
@ -64,7 +75,10 @@ __cexpl (__complex__ long double x)
__imag__ retval = __nanl ("");
}
else
retval = 0.0;
{
__real__ retval = 0.0;
__imag__ retval = __copysignl (0.0, __imag__ x);
}
}
else
{

View File

@ -0,0 +1,102 @@
/* Complex sine hyperbole function for double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
__complex__ double
__csinh (__complex__ double x)
{
__complex__ double retval;
int negate = signbit (__real__ x);
__real__ x = fabs (__real__ x);
if (isfinite (__real__ x))
{
if (isfinite (__imag__ x))
{
double exp_val = __exp (__real__ x);
double rec_exp_val = 1.0 / exp_val;
__real__ retval = 0.5 * (exp_val - rec_exp_val) * __cos (__imag__ x);
__imag__ retval = 0.5 * (exp_val - rec_exp_val) * __sin (__imag__ x);
if (negate)
__real__ retval = -__real__ retval;
}
else
{
if (__real__ x == 0)
{
__real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
__imag__ retval = __nan ("") + __nan ("");
}
else
{
__real__ retval = __nan ("");
__imag__ retval = __nan ("");
}
}
}
else if (__isinf (__real__ x))
{
if (__imag__ x == 0.0)
{
__real__ retval = negate ? -HUGE_VAL : HUGE_VAL;
__imag__ retval = __imag__ x;
}
else if (isfinite (__imag__ x))
{
__real__ retval = __copysign (HUGE_VAL, __cos (__imag__ x));
__imag__ retval = __copysign (HUGE_VAL, __sin (__imag__ x));
if (negate)
__real__ retval = -__real__ retval;
}
else
{
/* The addition raises the invalid exception. */
__real__ retval = HUGE_VAL;
__imag__ retval = __nan ("") + __nan ("");
}
}
else
{
if (__imag__ x == 0.0)
{
__real__ retval = __nan ("");
__imag__ retval = __imag__ x;
}
else
{
__real__ retval = __nan ("");
__imag__ retval = __nan ("");
}
}
return retval;
}
weak_alias (__csinh, csinh)
#ifdef NO_LONG_DOUBLE
strong_alias (__csinh, __csinhl)
weak_alias (__csinh, csinhl)
#endif

View File

@ -0,0 +1,100 @@
/* Complex sine hyperbole function for float.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
__complex__ float
__csinhf (__complex__ float x)
{
__complex__ float retval;
int negate = signbit (__real__ x);
__real__ x = fabsf (__real__ x);
if (isfinite (__real__ x))
{
if (isfinite (__imag__ x))
{
float exp_val = __expf (__real__ x);
float rec_exp_val = 1.0 / exp_val;
__real__ retval = (0.5 * (exp_val - rec_exp_val)
* __cosf (__imag__ x));
__imag__ retval = (0.5 * (exp_val - rec_exp_val)
* __sinf (__imag__ x));
if (negate)
__real__ retval = -__real__ retval;
}
else
{
if (__real__ x == 0)
{
__real__ retval = __copysignf (0.0, negate ? -1.0 : 1.0);
__imag__ retval = __nanf ("") + __nanf ("");
}
else
{
__real__ retval = __nanf ("");
__imag__ retval = __nanf ("");
}
}
}
else if (__isinff (__real__ x))
{
if (__imag__ x == 0.0)
{
__real__ retval = negate ? -HUGE_VALF : HUGE_VALF;
__imag__ retval = __imag__ x;
}
else if (isfinite (__imag__ x))
{
__real__ retval = __copysignf (HUGE_VALF, __cosf (__imag__ x));
__imag__ retval = __copysignf (HUGE_VALF, __sinf (__imag__ x));
if (negate)
__real__ retval = -__real__ retval;
}
else
{
/* The addition raises the invalid exception. */
__real__ retval = HUGE_VALF;
__imag__ retval = __nanf ("") + __nanf ("");
}
}
else
{
if (__imag__ x == 0.0)
{
__real__ retval = __nanf ("");
__imag__ retval = __imag__ x;
}
else
{
__real__ retval = __nanf ("");
__imag__ retval = __nanf ("");
}
}
return retval;
}
weak_alias (__csinhf, csinhf)

View File

@ -0,0 +1,100 @@
/* Complex sine hyperbole function for long double.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <complex.h>
#include <math.h>
__complex__ long double
__csinhl (__complex__ long double x)
{
__complex__ long double retval;
int negate = signbit (__real__ x);
__real__ x = fabs (__real__ x);
if (isfinite (__real__ x))
{
if (isfinite (__imag__ x))
{
long double exp_val = __expl (__real__ x);
long double rec_exp_val = 1.0 / exp_val;
__real__ retval = (0.5 * (exp_val - rec_exp_val)
* __cosl (__imag__ x));
__imag__ retval = (0.5 * (exp_val - rec_exp_val)
* __sinl (__imag__ x));
if (negate)
__real__ retval = -__real__ retval;
}
else
{
if (__real__ x == 0)
{
__real__ retval = __copysignl (0.0, negate ? -1.0 : 1.0);
__imag__ retval = __nanl ("") + __nanl ("");
}
else
{
__real__ retval = __nanl ("");
__imag__ retval = __nanl ("");
}
}
}
else if (__isinfl (__real__ x))
{
if (__imag__ x == 0.0)
{
__real__ retval = negate ? -HUGE_VALL : HUGE_VALL;
__imag__ retval = __imag__ x;
}
else if (isfinite (__imag__ x))
{
__real__ retval = __copysignl (HUGE_VALL, __cosl (__imag__ x));
__imag__ retval = __copysignl (HUGE_VALL, __sinl (__imag__ x));
if (negate)
__real__ retval = -__real__ retval;
}
else
{
/* The addition raises the invalid exception. */
__real__ retval = HUGE_VALL;
__imag__ retval = __nanl ("") + __nanl ("");
}
}
else
{
if (__imag__ x == 0.0)
{
__real__ retval = __nanl ("");
__imag__ retval = __imag__ x;
}
else
{
__real__ retval = __nanl ("");
__imag__ retval = __nanl ("");
}
}
return retval;
}
weak_alias (__csinhl, csinhl)

View File

@ -45,7 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* getaddrinfo() v1.13 */
/* To do what POSIX says, even when it's broken: */
/* #define BROKEN_LIKE_POSIX 1 */
#define BROKEN_LIKE_POSIX 1
#define LOCAL 1
#define INET6 1
#define HOSTTABLE 0
@ -168,21 +168,34 @@ static int gaih_local(const char *name, const struct gaih_service *service,
};
#endif /* LOCAL */
static struct gaih_typeproto gaih_inet_typeproto[] = {
static struct gaih_typeproto gaih_inet_typeproto[] =
{
{ 0, 0, NULL },
{ SOCK_STREAM, IPPROTO_TCP, (char *)"tcp" },
{ SOCK_DGRAM, IPPROTO_UDP, (char *)"udp" },
{ SOCK_STREAM, IPPROTO_TCP, (char *) "tcp" },
{ SOCK_DGRAM, IPPROTO_UDP, (char *) "udp" },
{ 0, 0, NULL }
};
static int gaih_inet_serv(char *servicename, struct gaih_typeproto *tp, struct gaih_servtuple **st)
{
struct servent *s;
int tmpbuflen = 1024;
struct servent ts;
char *tmpbuf = __alloca (tmpbuflen);
while (__getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s))
{
if (errno == ERANGE)
{
tmpbuflen *= 2;
tmpbuf = __alloca (tmpbuflen);
}
else
{
return GAIH_OKIFUNSPEC | -EAI_SERVICE;
}
}
if (!(s = getservbyname(servicename, tp->name)))
return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
if (!(*st = malloc(sizeof(struct gaih_servtuple))))
if (!(*st = malloc (sizeof (struct gaih_servtuple))))
return -EAI_MEMORY;
(*st)->next = NULL;

View File

@ -1,20 +1,20 @@
/* Copyright (C) 1991, 92, 94, 95, 96 Free Software Foundation, Inc.
This file is part of the GNU C Library.
/* Copyright (C) 1991, 92, 94, 95, 96, 97 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stddef.h>
#include <stdlib.h>

View File

@ -105,7 +105,12 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
Elf32_Addr loadbase;
if (ELF32_R_TYPE (reloc->r_info) == R_SPARC_RELATIVE)
*reloc_addr += map->l_addr + reloc->r_addend;
{
#ifndef RTLD_BOOTSTRAP
if (map != &_dl_rtld_map) /* Already done in rtld itself. */
#endif
*reloc_addr += map->l_addr + reloc->r_addend;
}
else
{
Elf32_Addr value;

View File

@ -1,6 +1,6 @@
! SPARC __udiv_qrnnd division support, used from longlong.h.
! Copyright (C) 1993, 1994 Free Software Foundation, Inc.
! Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc.
! This file is part of the GNU MP Library.
@ -18,6 +18,8 @@
! along with the GNU MP Library; see the file COPYING.LIB. If not, write to
! the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! Added PIC support - May/96, Miguel de Icaza
! INPUT PARAMETERS
! rem_ptr i0
@ -25,6 +27,7 @@
! n0 i2
! d i3
#include "DEFS.h"
#include "sysdep.h"
#undef ret /* Kludge for glibc */
@ -34,16 +37,25 @@ LC0: .double 0r4294967296
LC1: .double 0r2147483648
.align 4
.global C_SYMBOL_NAME(__udiv_qrnnd)
C_SYMBOL_NAME(__udiv_qrnnd):
.global __udiv_qrnnd
FUNC(__udiv_qrnnd)
!#PROLOGUE# 0
save %sp,-104,%sp
!#PROLOGUE# 1
st %i1,[%fp-8]
ld [%fp-8],%f10
#ifdef __PIC__
._XL11:
call ._XL1
fitod %f10,%f4
._XL1:
sub %o7,(._XL11-LC0),%o7
ldd [%o7],%f8
#else
sethi %hi(LC0),%o7
fitod %f10,%f4
ldd [%o7+%lo(LC0)],%f8
#endif
cmp %i1,0
bge L248
mov %i0,%i5
@ -66,8 +78,17 @@ L249:
faddd %f4,%f8,%f4
L250:
fdivd %f2,%f4,%f2
#ifdef __PIC__
._XL22:
call ._XL2
nop
._XL2:
sub %o7,(._XL22-LC1),%o7
ldd [%o7],%f4
#else
sethi %hi(LC1),%o7
ldd [%o7+%lo(LC1)],%f4
#endif
fcmped %f2,%f4
nop
fbge,a L251

View File

@ -3,3 +3,5 @@ clone.S
start.c
pipe.S
fork.S
kernel_stat.h
kernel_sigaction.h

View File

@ -0,0 +1,96 @@
/* O_*, F_*, FD_* bit values for Linux/SPARC.
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _FCNTLBITS_H
#define _FCNTLBITS_H 1
#include <sys/types.h>
/* In GNU, read and write are bits (unlike BSD). */
#ifdef __USE_GNU
#define O_READ O_RDONLY /* Open for reading. */
#define O_WRITE O_WRONLY /* Open for writing. */
#endif
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
#define O_RDONLY 0x0000
#define O_WRONLY 0x0001
#define O_RDWR 0x0002
#define O_ACCMODE 0x0003
#define O_APPEND 0x0008
#define O_CREAT 0x0200 /* not fcntl */
#define O_TRUNC 0x0400 /* not fcntl */
#define O_EXCL 0x0800 /* not fcntl */
#define O_SYNC 0x2000
#define O_NONBLOCK 0x4000
#define O_NDELAY (0x0004 | O_NONBLOCK)
#define O_NOCTTY 0x8000 /* not fcntl */
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */
#define F_SETFD 2 /* set f_flags */
#define F_GETFL 3 /* more flags (cloexec) */
#define F_SETFL 4
#define F_GETOWN 5 /* for sockets. */
#define F_SETOWN 6 /* for sockets. */
#define F_GETLK 7
#define F_SETLK 8
#define F_SETLKW 9
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* for posix fcntl() and lockf() */
#define F_RDLCK 1
#define F_WRLCK 2
#define F_UNLCK 3
/* for old implementation of bsd flock () */
#define F_EXLCK 4 /* or 3 */
#define F_SHLCK 8 /* or 4 */
/* operations for bsd flock(), also used by the kernel implementation */
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* or'd with one of the above to prevent
blocking */
#define LOCK_UN 8 /* remove lock */
struct flock
{
short int l_type;
short int l_whence;
__off_t l_start;
__off_t l_len;
__pid_t l_pid;
short int __unused;
};
/* Define some more compatibility macros to be backward compatible with
BSD systems which did not managed to hide these kernel macros. */
#ifdef __USE_BSD
#define FAPPEND O_APPEND
#define FFSYNC O_FSYNC
#define FASYNC O_ASYNC
#define FNONBLOCK O_NONBLOCK
#define FNDELAY O_NDELAY
#endif /* Use BSD. */
#endif

View File

@ -0,0 +1,39 @@
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _IOCTLS_H
#define _IOCTLS_H 1
/* Use the definitions from the kernel header files. */
#include <asm/ioctls.h>
#include <sys/kernel_termios.h>
/* Oh well, this is necessary since the kernel data structure is
different from the user-level version. */
#undef TCGETS
#undef TCSETS
#undef TCSETSW
#undef TCSETSF
#define TCGETS _IOR ('t', 19, struct __kernel_termios)
#define TCSETS _IOW ('t', 20, struct __kernel_termios)
#define TCSETSW _IOW ('t', 21, struct __kernel_termios)
#define TCSETSF _IOW ('t', 22, struct __kernel_termios)
#include <linux/sockios.h>
#endif /* ioctls.h */

View File

@ -0,0 +1,12 @@
/* Linux/SPARC version. This is the sigaction struction from the Linux
2.1.20 kernel. */
struct sigaction
{
__sighandler_t sa_handler;
sigset_t sa_mask;
unsigned long int sa_flags;
void (*sa_restorer) (void); /* not used by Linux/SPARC yet */
};
#define HAVE_SA_RESTORER

View File

@ -0,0 +1,21 @@
/* Definition of `struct stat' used in the kernel */
struct kernel_stat
{
unsigned short int st_dev;
unsigned long int st_ino;
unsigned short int st_mode;
short int st_nlink;
unsigned short int st_uid;
unsigned short int st_gid;
unsigned short int st_rdev;
long int st_size;
long int st_atime;
unsigned long int __unused1;
long int st_mtime;
unsigned long int __unused2;
long int st_ctime;
unsigned long int __unused3;
long int st_blksize;
long int st_blocks;
unsigned long int __unused4[2];
};

View File

@ -0,0 +1,52 @@
/* The proper definitions for Linux/SPARC sigaction.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Structure describing the action to be taken when a signal arrives. */
struct sigaction
{
/* Signal handler. */
__sighandler_t sa_handler;
/* Additional set of signals to be blocked. */
__sigset_t sa_mask;
/* Special flags. */
unsigned int sa_flags;
};
/* Bits in `sa_flags'. */
#define SA_NOCLDSTOP 0x00000008 /* Don't send SIGCHLD when children stop. */
#ifdef __USE_MISC
#define SA_STACK 0x00000001 /* Use signal stack by using `sa_restorer'. */
#define SA_RESTART 0x00000002 /* Don't restart syscall on signal return. */
#define SA_INTERRUPT 0x00000010 /* Historical no-op. */
#define SA_NOMASK 0x00000020 /* Don't automatically block the signal when
its handler is being executed. */
#define SA_ONESHOT 0x00000004 /* Reset to SIG_DFL on entry to handler. */
/* Some aliases for the SA_ constants. */
#define SA_NODEFER SA_NOMASK
#define SA_RESETHAND SA_ONESHOT
#endif
/* Values for the HOW argument to `sigprocmask'. */
#define SIG_BLOCK 1 /* Block signals. */
#define SIG_UNBLOCK 2 /* Unblock signals. */
#define SIG_SETMASK 4 /* Set the set of blocked signals. */

View File

@ -0,0 +1,72 @@
/* Signal number definitions. Linux/SPARC version.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef _SIGNAL_H
/* Fake signal functions. */
#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
/*
* Linux/SPARC has different signal numbers that Linux/i386: I'm trying
* to make it OSF/1 binary compatible, at least for normal binaries.
*/
#define _NSIG 32 /* Biggest signal number + 1. */
#define NSIG _NSIG
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGEMT 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGBUS 10
#define SIGSEGV 11
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGURG 16
/* SunOS values which deviate from the Linux/i386 ones */
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGIO 23
#define SIGPOLL SIGIO /* SysV name for SIGIO */
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGLOST 29
#define SIGUSR1 30
#define SIGUSR2 31
/* Linux/SPARC does not have SIGPWR */
#define SIGIOT SIGABRT
#endif /* <signal.h> included. */

View File

@ -0,0 +1,217 @@
/* termios type and macro definitions. Linux/SPARC version.
Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _SPARC_TERMBITS_H
#define _SPARC_TERMBITS_H 1
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned long tcflag_t;
#define NCCS 17
struct termios
{
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
#ifdef __KERNEL__
#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t))
cc_t _x_cc[2]; /* We need them to hold vmin/vtime */
#endif
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VEOL 5
#define VEOL2 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is
* shared with eof/eol
*/
#ifdef __KERNEL__
#define VMIN 16
#define VTIME 17
#else
#define VMIN VEOF
#define VTIME VEOL
#endif
/* c_iflag bits */
#define IGNBRK 0x00000001
#define BRKINT 0x00000002
#define IGNPAR 0x00000004
#define PARMRK 0x00000008
#define INPCK 0x00000010
#define ISTRIP 0x00000020
#define INLCR 0x00000040
#define IGNCR 0x00000080
#define ICRNL 0x00000100
#define IUCLC 0x00000200
#define IXON 0x00000400
#define IXANY 0x00000800
#define IXOFF 0x00001000
#define IMAXBEL 0x00002000
/* c_oflag bits */
#define OPOST 0x00000001
#define OLCUC 0x00000002
#define ONLCR 0x00000004
#define OCRNL 0x00000008
#define ONOCR 0x00000010
#define ONLRET 0x00000020
#define OFILL 0x00000040
#define OFDEL 0x00000080
#define NLDLY 0x00000100
#define NL0 0x00000000
#define NL1 0x00000100
#define CRDLY 0x00000600
#define CR0 0x00000000
#define CR1 0x00000200
#define CR2 0x00000400
#define CR3 0x00000600
#define TABDLY 0x00001800
#define TAB0 0x00000000
#define TAB1 0x00000800
#define TAB2 0x00001000
#define TAB3 0x00001800
#define XTABS 0x00001800
#define BSDLY 0x00002000
#define BS0 0x00000000
#define BS1 0x00002000
#define VTDLY 0x00004000
#define VT0 0x00000000
#define VT1 0x00004000
#define FFDLY 0x00008000
#define FF0 0x00000000
#define FF1 0x00008000
#define PAGEOUT 0x00010000 /* SUNOS specific */
#define WRAP 0x00020000 /* SUNOS specific */
/* c_cflag bit meaning */
#define CBAUD 0x0000000f
#define B0 0x00000000 /* hang up */
#define B50 0x00000001
#define B75 0x00000002
#define B110 0x00000003
#define B134 0x00000004
#define B150 0x00000005
#define B200 0x00000006
#define B300 0x00000007
#define B600 0x00000008
#define B1200 0x00000009
#define B1800 0x0000000a
#define B2400 0x0000000b
#define B4800 0x0000000c
#define B9600 0x0000000d
#define B19200 0x0000000e
#define B38400 0x0000000f
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0x00000030
#define CS5 0x00000000
#define CS6 0x00000010
#define CS7 0x00000020
#define CS8 0x00000030
#define CSTOPB 0x00000040
#define CREAD 0x00000080
#define PARENB 0x00000100
#define PARODD 0x00000200
#define HUPCL 0x00000400
#define CLOCAL 0x00000800
/* We'll never see these speeds with the Zilogs' but for completeness... */
#define CBAUDEX 0x00010000
#define B57600 0x00010001
#define B115200 0x00010002
#define B230400 0x00010003
#define B460800 0x00010004
#define CIBAUD 0x000f0000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 0x80000000 /* flow control */
/* c_lflag bits */
#define ISIG 0x00000001
#define ICANON 0x00000002
#define XCASE 0x00000004
#define ECHO 0x00000008
#define ECHOE 0x00000010
#define ECHOK 0x00000020
#define ECHONL 0x00000040
#define NOFLSH 0x00000080
#define TOSTOP 0x00000100
#define ECHOCTL 0x00000200
#define ECHOPRT 0x00000400
#define ECHOKE 0x00000800
#define DEFECHO 0x00001000 /* SUNOS thing, what is it? */
#define FLUSHO 0x00002000
#define PENDIN 0x00004000
#define IEXTEN 0x00008000
/* modem lines */
#define TIOCM_LE 0x001
#define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004
#define TIOCM_ST 0x008
#define TIOCM_SR 0x010
#define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
#endif /* !(_SPARC_TERMBITS_H) */