user: implement mlibc as the libc, finally.

It's finally done..

Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
kaguya
2026-05-02 03:31:49 -04:00
parent 2fa39ad85a
commit 9a9b91c940
2387 changed files with 152741 additions and 315 deletions
@@ -0,0 +1,13 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/ensure.h>
[[gnu::noreturn]] void __assert_fail(const char *assertion, const char *file, unsigned int line,
const char *function) {
fprintf(stderr, "In function %s, file %s:%d: Assertion '%s' failed!\n",
function, file, line, assertion);
abort();
}
@@ -0,0 +1,9 @@
#include <complex.h>
long double cimagl(long double complex z) {
return __imag__(z);
}
long double creall(long double complex z) {
return __real__(z);
}
@@ -0,0 +1,59 @@
/* $NetBSD: cabs.c,v 1.1 2007/08/20 16:01:30 drochner Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cabs>>, <<cabsf>>, <<cabsl>>---complex absolute-value
INDEX
cabs
INDEX
cabsf
INDEX
cabsl
SYNOPSIS
#include <complex.h>
double cabs(double complex <[z]>);
float cabsf(float complex <[z]>);
long double cabsl(long double complex <[z]>);
DESCRIPTION
These functions compute compute the complex absolute value
(also called norm, modulus, or magnitude) of <[z]>.
<<cabsf>> is identical to <<cabs>>, except that it performs
its calculations on <<float complex>>.
<<cabsl>> is identical to <<cabs>>, except that it performs
its calculations on <<long double complex>>.
RETURNS
The cabs* functions return the complex absolute value.
PORTABILITY
<<cabs>>, <<cabsf>> and <<cabsl>> are ISO C99
QUICKREF
<<cabs>>, <<cabsf>> and <<cabsl>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double
cabs(double complex z)
{
return hypot( creal(z), cimag(z) );
}
@@ -0,0 +1,19 @@
/* $NetBSD: cabsf.c,v 1.1 2007/08/20 16:01:30 drochner Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float
cabsf(float complex z)
{
return hypotf( crealf(z), cimagf(z) );
}
@@ -0,0 +1,99 @@
/* $NetBSD: cacos.c,v 1.1 2007/08/20 16:01:30 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cacos>>, <<cacosf>>---complex arc cosine
INDEX
cacos
INDEX
cacosf
SYNOPSIS
#include <complex.h>
double complex cacos(double complex <[z]>);
float complex cacosf(float complex <[z]>);
DESCRIPTION
These functions compute the complex arc cosine of <[z]>,
with branch cuts outside the interval [-1, +1] along the real axis.
<<cacosf>> is identical to <<cacos>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
These functions return the complex arc cosine value, in the range
of a strip mathematically unbounded along the imaginary axis
and in the interval [0, pi] along the real axis.
@end ifnottex
@tex
These functions return the complex arc cosine value, in the range
of a strip mathematically unbounded along the imaginary axis
and in the interval [<<0>>, $\pi$] along the real axis.
@end tex
PORTABILITY
<<cacos>> and <<cacosf>> are ISO C99
QUICKREF
<<cacos>> and <<cacosf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
cacos(double complex z)
{
double complex w;
/* FIXME: The original NetBSD code results in an ICE when trying to
build this function on ARM/Thumb using gcc 4.5.1. For now we use
a hopefully temporary workaround. */
#if 0
w = casin(z);
w = (M_PI_2 - creal(w)) - cimag(w) * I;
#else
double complex tmp0, tmp1;
tmp0 = casin(z);
tmp1 = M_PI_2 - creal(tmp0);
w = tmp1 - (cimag(tmp0) * I);
#endif
return w;
}
@@ -0,0 +1,46 @@
/* $NetBSD: cacosf.c,v 1.1 2007/08/20 16:01:30 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
cacosf(float complex z)
{
float complex w;
w = casinf(z);
w = ((float)M_PI_2 - crealf(w)) - cimagf(w) * I;
return w;
}
@@ -0,0 +1,93 @@
/* $NetBSD: cacosh.c,v 1.2 2009/08/03 19:41:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cacosh>>, <<cacoshf>>---complex arc hyperbolic cosine
INDEX
cacosh
INDEX
cacoshf
SYNOPSIS
#include <complex.h>
double complex cacosh(double complex <[z]>);
float complex cacoshf(float complex <[z]>);
DESCRIPTION
These functions compute the complex arc hyperbolic cosine of <[z]>,
with a branch cut at values less than 1 along the real axis.
<<cacoshf>> is identical to <<cacosh>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
These functions return the complex arc hyperbolic cosine value,
in the range of a half-strip of non-negative values along the
real axis and in the interval [-i * pi, +i * pi] along the
imaginary axis.
@end ifnottex
@tex
These functions return the complex arc hyperbolic cosine value,
in the range of a half-strip of non-negative values along the
real axis and in the interval [$-i\pi$, $+i\pi$] along the
imaginary axis.
@end tex
PORTABILITY
<<cacosh>> and <<cacoshf>> are ISO C99
QUICKREF
<<cacosh>> and <<cacoshf>> are ISO C99
*/
#include <complex.h>
double complex
cacosh(double complex z)
{
double complex w;
#if 0 /* does not give the principal value */
w = I * cacos(z);
#else
w = clog(z + csqrt(z + 1) * csqrt(z - 1));
#endif
return w;
}
@@ -0,0 +1,48 @@
/* $NetBSD: cacoshf.c,v 1.2 2009/08/03 19:41:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
float complex
cacoshf(float complex z)
{
float complex w;
#if 0 /* does not give the principal value */
w = I * cacosf(z);
#else
w = clogf(z + csqrtf(z + 1) * csqrtf(z - 1));
#endif
return w;
}
@@ -0,0 +1,59 @@
/* $NetBSD: carg.c,v 1.1 2007/08/20 16:01:31 drochner Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<carg>>, <<cargf>>---argument (phase angle)
INDEX
carg
INDEX
cargf
SYNOPSIS
#include <complex.h>
double carg(double complex <[z]>);
float cargf(float complex <[z]>);
DESCRIPTION
These functions compute the argument (also called phase angle)
of <[z]>, with a branch cut along the negative real axis.
<<cargf>> is identical to <<carg>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
The carg functions return the value of the argument in the
interval [-pi, +pi]
@end ifnottex
@tex
The carg functions return the value of the argument in the
interval [$-\pi$, $+\pi$]
@end tex
PORTABILITY
<<carg>> and <<cargf>> are ISO C99
QUICKREF
<<carg>> and <<cargf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double
carg(double complex z)
{
return atan2( cimag(z) , creal(z) );
}
@@ -0,0 +1,19 @@
/* $NetBSD: cargf.c,v 1.1 2007/08/20 16:01:31 drochner Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float
cargf(float complex z)
{
return atan2f( cimagf(z), crealf(z) );
}
@@ -0,0 +1,165 @@
/* $NetBSD: casin.c,v 1.1 2007/08/20 16:01:31 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<casin>>, <<casinf>>---complex arc sine
INDEX
casin
INDEX
casinf
SYNOPSIS
#include <complex.h>
double complex casin(double complex <[z]>);
float complex casinf(float complex <[z]>);
DESCRIPTION
These functions compute the complex arc sine of <[z]>,
with branch cuts outside the interval [-1, +1] along the real axis.
<<casinf>> is identical to <<casin>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
These functions return the complex arc sine value, in the range
of a strip mathematically unbounded along the imaginary axis
and in the interval [-pi/2, +pi/2] along the real axis.
@end ifnottex
@tex
These functions return the complex arc sine value, in the range
of a strip mathematically unbounded along the imaginary axis
and in the interval [$-\pi/2$, $+\pi/2$] along the real axis.
@end tex
PORTABILITY
<<casin>> and <<casinf>> are ISO C99
QUICKREF
<<casin>> and <<casinf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
#ifdef __weak_alias
__weak_alias(casin, _casin)
#endif
double complex
casin(double complex z)
{
double complex w;
double complex ca, ct, zz, z2;
double x, y;
x = creal(z);
y = cimag(z);
#if 0 /* MD: test is incorrect, casin(>1) is defined */
if (y == 0.0) {
if (fabs(x) > 1.0) {
w = M_PI_2 + 0.0 * I;
#if 0
mtherr ("casin", DOMAIN);
#endif
} else {
w = asin(x) + 0.0 * I;
}
return w;
}
#endif
/* Power series expansion */
/*
b = cabs(z);
if( b < 0.125 )
{
z2.r = (x - y) * (x + y);
z2.i = 2.0 * x * y;
cn = 1.0;
n = 1.0;
ca.r = x;
ca.i = y;
sum.r = x;
sum.i = y;
do
{
ct.r = z2.r * ca.r - z2.i * ca.i;
ct.i = z2.r * ca.i + z2.i * ca.r;
ca.r = ct.r;
ca.i = ct.i;
cn *= n;
n += 1.0;
cn /= n;
n += 1.0;
b = cn/n;
ct.r *= b;
ct.i *= b;
sum.r += ct.r;
sum.i += ct.i;
b = fabs(ct.r) + fabs(ct.i);
}
while( b > MACHEP );
w->r = sum.r;
w->i = sum.i;
return;
}
*/
ca = x + y * I;
ct = ca * I;
/* sqrt( 1 - z*z) */
/* cmul( &ca, &ca, &zz ) */
/*x * x - y * y */
zz = (x - y) * (x + y) + (2.0 * x * y) * I;
zz = 1.0 - creal(zz) - cimag(zz) * I;
z2 = csqrt(zz);
zz = ct + z2;
zz = clog(zz);
/* multiply by 1/i = -i */
w = zz * (-1.0 * I);
return w;
}
@@ -0,0 +1,122 @@
/* $NetBSD: casinf.c,v 1.1 2007/08/20 16:01:31 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#ifdef __weak_alias
__weak_alias(casinf, _casinf)
#endif
float complex
casinf(float complex z)
{
float complex w;
float complex ca, ct, zz, z2;
float x, y;
x = crealf(z);
y = cimagf(z);
#if 0 /* MD: test is incorrect, casin(>1) is defined */
if (y == 0.0f) {
if (fabsf(x) > 1.0) {
w = M_PI_2 + 0.0f * I;
#if 0
mtherr ("casin", DOMAIN);
#endif
} else {
w = asinf(x) + 0.0f * I;
}
return w;
}
#endif
/* Power series expansion */
/*
b = cabsf(z);
if( b < 0.125 )
{
z2.r = (x - y) * (x + y);
z2.i = 2.0 * x * y;
cn = 1.0;
n = 1.0;
ca.r = x;
ca.i = y;
sum.r = x;
sum.i = y;
do
{
ct.r = z2.r * ca.r - z2.i * ca.i;
ct.i = z2.r * ca.i + z2.i * ca.r;
ca.r = ct.r;
ca.i = ct.i;
cn *= n;
n += 1.0;
cn /= n;
n += 1.0;
b = cn/n;
ct.r *= b;
ct.i *= b;
sum.r += ct.r;
sum.i += ct.i;
b = fabsf(ct.r) + fabsf(ct.i);
}
while( b > MACHEP );
w->r = sum.r;
w->i = sum.i;
return;
}
*/
ca = x + y * I;
ct = ca * I;
/* sqrt( 1 - z*z) */
/* cmul( &ca, &ca, &zz ) */
/*x * x - y * y */
zz = (x - y) * (x + y) + (2.0f * x * y) * I;
zz = 1.0f - crealf(zz) - cimagf(zz) * I;
z2 = csqrtf(zz);
zz = ct + z2;
zz = clogf(zz);
/* multiply by 1/i = -i */
w = zz * (-1.0f * I);
return w;
}
@@ -0,0 +1,97 @@
/* $NetBSD: casinh.c,v 1.1 2007/08/20 16:01:31 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<casinh>>, <<casinhf>>---complex arc hyperbolic sine
INDEX
casinh
INDEX
casinhf
SYNOPSIS
#include <complex.h>
double complex casinh(double complex <[z]>);
float complex casinhf(float complex <[z]>);
DESCRIPTION
@ifnottex
These functions compute the complex arc hyperbolic sine of <[z]>,
with branch cuts outside the interval [-i, +i] along the
imaginary axis.
@end ifnottex
@tex
These functions compute the complex arc hyperbolic sine of <[z]>,
with branch cuts outside the interval [$-i$, $+i$] along the
imaginary axis.
@end tex
<<casinhf>> is identical to <<casinh>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
These functions return the complex arc hyperbolic sine value,
in the range of a strip mathematically unbounded along the
real axis and in the interval [-i*p/2, +i*p/2] along the
imaginary axis.
@end ifnottex
@tex
These functions return the complex arc hyperbolic sine value,
in the range of a strip mathematically unbounded along the
real axis and in the interval [$-i\pi/2$, $+i\pi/2$] along the
imaginary axis.
@end tex
PORTABILITY
<<casinh>> and <<casinhf>> are ISO C99
QUICKREF
<<casinh>> and <<casinhf>> are ISO C99
*/
#include <complex.h>
double complex
casinh(double complex z)
{
double complex w;
w = -1.0 * I * casin(z * I);
return w;
}
@@ -0,0 +1,44 @@
/* $NetBSD: casinhf.c,v 1.1 2007/08/20 16:01:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
float complex
casinhf(float complex z)
{
float complex w;
w = -1.0f * I * casinf(z * I);
return w;
}
@@ -0,0 +1,128 @@
/* $NetBSD: catan.c,v 1.1 2007/08/20 16:01:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<catan>>, <<catanf>>---complex arc tangent
INDEX
catan
INDEX
catanf
SYNOPSIS
#include <complex.h>
double complex catan(double complex <[z]>);
float complex catanf(float complex <[z]>);
DESCRIPTION
@ifnottex
These functions compute the complex arc tangent of <[z]>,
with branch cuts outside the interval [-i, +i] along the
imaginary axis.
@end ifnottex
@tex
These functions compute the complex arc tangent of <[z]>,
with branch cuts outside the interval [$-i$, $+i$] along the
imaginary axis.
@end tex
<<catanf>> is identical to <<catan>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
These functions return the complex arc tangent value, in the range
of a strip mathematically unbounded along the imaginary axis
and in the interval [-pi/2, +pi/2] along the real axis.
@end ifnottex
@tex
These functions return the complex arc tangent, in the range
of a strip mathematically unbounded along the imaginary axis
and in the interval [$-\pi/2$, $+\pi/2$] along the real axis.
@end tex
PORTABILITY
<<catan>> and <<catanf>> are ISO C99
QUICKREF
<<catan>> and <<catanf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
#include "cephes_subr.h"
#ifdef __weak_alias
__weak_alias(catan, _catan)
#endif
double complex
catan(double complex z)
{
double complex w;
double a, t, x, x2, y;
x = creal(z);
y = cimag(z);
if ((x == 0.0) && (y > 1.0))
goto ovrf;
x2 = x * x;
a = 1.0 - x2 - (y * y);
t = 0.5 * atan2(2.0 * x, a);
w = _redupi(t);
t = y - 1.0;
a = x2 + (t * t);
if (a == 0.0)
goto ovrf;
t = y + 1.0;
a = (x2 + (t * t))/a;
w = w + (0.25 * log(a)) * I;
return w;
ovrf:
#if 0
mtherr ("catan", OVERFLOW);
#endif
w = HUGE_VAL + HUGE_VAL * I;
return w;
}
@@ -0,0 +1,77 @@
/* $NetBSD: catanf.c,v 1.1 2007/08/20 16:01:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#include "cephes_subrf.h"
#ifdef __weak_alias
__weak_alias(catanf, _catanf)
#endif
float complex
catanf(float complex z)
{
float complex w;
float a, t, x, x2, y;
x = crealf(z);
y = cimagf(z);
if ((x == 0.0f) && (y > 1.0f))
goto ovrf;
x2 = x * x;
a = 1.0f - x2 - (y * y);
t = 0.5f * atan2f(2.0f * x, a);
w = _redupif(t);
t = y - 1.0f;
a = x2 + (t * t);
if (a == 0.0f)
goto ovrf;
t = y + 1.0f;
a = (x2 + (t * t))/a;
w = w + (0.25f * logf(a)) * I;
return w;
ovrf:
#if 0
mtherr ("catan", OVERFLOW);
#endif
w = HUGE_VALF + HUGE_VALF * I;
return w;
}
@@ -0,0 +1,90 @@
/* $NetBSD: catanh.c,v 1.1 2007/08/20 16:01:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<catanh>>, <<catanhf>>---complex arc hyperbolic tangent
INDEX
catanh
INDEX
catanhf
SYNOPSIS
#include <complex.h>
double complex catanh(double complex <[z]>);
float complex catanhf(float complex <[z]>);
DESCRIPTION
These functions compute the complex arc hyperbolic tan of <[z]>,
with branch cuts outside the interval [-1, +1] along the
real axis.
<<catanhf>> is identical to <<catanh>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
These functions return the complex arc hyperbolic tangent value,
in the range of a strip mathematically unbounded along the
real axis and in the interval [-i*p/2, +i*p/2] along the
imaginary axis.
@end ifnottex
@tex
These functions return the complex arc hyperbolic tangent value,
in the range of a strip mathematically unbounded along the
real axis and in the interval [$-i\pi/2$, $+i\pi/2$] along the
imaginary axis.
@end tex
PORTABILITY
<<catanh>> and <<catanhf>> are ISO C99
QUICKREF
<<catanh>> and <<catanhf>> are ISO C99
*/
#include <complex.h>
double complex
catanh(double complex z)
{
double complex w;
w = -1.0 * I * catan(z * I);
return w;
}
@@ -0,0 +1,44 @@
/* $NetBSD: catanhf.c,v 1.1 2007/08/20 16:01:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
float complex
catanhf(float complex z)
{
float complex w;
w = -1.0f * I * catanf(z * I);
return w;
}
@@ -0,0 +1,81 @@
/* $NetBSD: ccos.c,v 1.1 2007/08/20 16:01:32 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<ccos>>, <<ccosf>>---complex cosine
INDEX
ccos
INDEX
ccosf
SYNOPSIS
#include <complex.h>
double complex ccos(double complex <[z]>);
float complex ccosf(float complex <[z]>);
DESCRIPTION
These functions compute the complex cosine of <[z]>.
<<ccosf>> is identical to <<ccos>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
These functions return the complex cosine value.
PORTABILITY
<<ccos>> and <<ccosf>> are ISO C99
QUICKREF
<<ccos>> and <<ccosf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
#include "cephes_subr.h"
double complex
ccos(double complex z)
{
double complex w;
double ch, sh;
_cchsh(cimag(z), &ch, &sh);
w = cos(creal(z)) * ch - (sin(creal(z)) * sh) * I;
return w;
}
@@ -0,0 +1,48 @@
/* $NetBSD: ccosf.c,v 1.1 2007/08/20 16:01:33 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#include "cephes_subrf.h"
float complex
ccosf(float complex z)
{
float complex w;
float ch, sh;
_cchshf(cimagf(z), &ch, &sh);
w = cosf(crealf(z)) * ch - (sinf(crealf(z)) * sh) * I;
return w;
}
@@ -0,0 +1,81 @@
/* $NetBSD: ccosh.c,v 1.1 2007/08/20 16:01:33 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<ccosh>>, <<ccoshf>>---complex hyperbolic cosine
INDEX
ccosh
INDEX
ccoshf
SYNOPSIS
#include <complex.h>
double complex ccosh(double complex <[z]>);
float complex ccoshf(float complex <[z]>);
DESCRIPTION
These functions compute the complex hyperbolic cosine of <[z]>.
<<ccoshf>> is identical to <<ccosh>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
These functions return the complex hyperbolic cosine value.
PORTABILITY
<<ccosh>> and <<ccoshf>> are ISO C99
QUICKREF
<<ccosh>> and <<ccoshf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
ccosh(double complex z)
{
double complex w;
double x, y;
x = creal(z);
y = cimag(z);
w = cosh(x) * cos(y) + (sinh(x) * sin(y)) * I;
return w;
}
@@ -0,0 +1,48 @@
/* $NetBSD: ccoshf.c,v 1.1 2007/08/20 16:01:33 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
ccoshf(float complex z)
{
float complex w;
float x, y;
x = crealf(z);
y = cimagf(z);
w = coshf(x) * cosf(y) + (sinhf(x) * sinf(y)) * I;
return w;
}
@@ -0,0 +1,126 @@
/* $NetBSD: cephes_subr.c,v 1.1 2007/08/20 16:01:33 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#include "cephes_subr.h"
/* calculate cosh and sinh */
void
_cchsh(double x, double *c, double *s)
{
double e, ei;
if (fabs(x) <= 0.5) {
*c = cosh(x);
*s = sinh(x);
} else {
e = exp(x);
ei = 0.5 / e;
e = 0.5 * e;
*s = e - ei;
*c = e + ei;
}
}
/* Program to subtract nearest integer multiple of PI */
/* extended precision value of PI: */
static const double DP1 = 3.14159265160560607910E0;
static const double DP2 = 1.98418714791870343106E-9;
static const double DP3 = 1.14423774522196636802E-17;
#define MACHEP 1.1e-16
double
_redupi(double x)
{
double t;
long i;
t = x / M_PI;
if (t >= 0.0)
t += 0.5;
else
t -= 0.5;
i = t; /* the multiple */
t = i;
t = ((x - t * DP1) - t * DP2) - t * DP3;
return t;
}
/* Taylor series expansion for cosh(2y) - cos(2x) */
double
_ctans(double complex z)
{
double f, x, x2, y, y2, rn, t;
double d;
x = fabs(2.0 * creal(z));
y = fabs(2.0 * cimag(z));
x = _redupi(x);
x = x * x;
y = y * y;
x2 = 1.0;
y2 = 1.0;
f = 1.0;
rn = 0.0;
d = 0.0;
do {
rn += 1.0;
f *= rn;
rn += 1.0;
f *= rn;
x2 *= x;
y2 *= y;
t = y2 + x2;
t /= f;
d += t;
rn += 1.0;
f *= rn;
rn += 1.0;
f *= rn;
x2 *= x;
y2 *= y;
t = y2 - x2;
t /= f;
d += t;
} while (fabs(t/d) > MACHEP);
return d;
}
@@ -0,0 +1,8 @@
/* $NetBSD: cephes_subr.h,v 1.1 2007/08/20 16:01:33 drochner Exp $ */
__attribute__((__visibility__("hidden")))
void _cchsh(double, double *, double *);
__attribute__((__visibility__("hidden")))
double _redupi(double);
__attribute__((__visibility__("hidden")))
double _ctans(double complex);
@@ -0,0 +1,125 @@
/* $NetBSD: cephes_subrf.c,v 1.1 2007/08/20 16:01:34 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#include "cephes_subrf.h"
/* calculate cosh and sinh */
void
_cchshf(float x, float *c, float *s)
{
float e, ei;
if (fabsf(x) <= 0.5f) {
*c = coshf(x);
*s = sinhf(x);
} else {
e = expf(x);
ei = 0.5f / e;
e = 0.5f * e;
*s = e - ei;
*c = e + ei;
}
}
/* Program to subtract nearest integer multiple of PI */
/* extended precision value of PI: */
static const double DP1 = 3.140625;
static const double DP2 = 9.67502593994140625E-4;
static const double DP3 = 1.509957990978376432E-7;
#define MACHEPF 3.0e-8
float
_redupif(float x)
{
float t;
long i;
t = x / (float)M_PI;
if (t >= 0.0f)
t += 0.5f;
else
t -= 0.5f;
i = t; /* the multiple */
t = i;
t = ((x - t * DP1) - t * DP2) - t * DP3;
return t;
}
/* Taylor series expansion for cosh(2y) - cos(2x) */
float
_ctansf(float complex z)
{
float f, x, x2, y, y2, rn, t, d;
x = fabsf(2.0f * crealf(z));
y = fabsf(2.0f * cimagf(z));
x = _redupif(x);
x = x * x;
y = y * y;
x2 = 1.0f;
y2 = 1.0f;
f = 1.0f;
rn = 0.0f;
d = 0.0f;
do {
rn += 1.0f;
f *= rn;
rn += 1.0f;
f *= rn;
x2 *= x;
y2 *= y;
t = y2 + x2;
t /= f;
d += t;
rn += 1.0f;
f *= rn;
rn += 1.0f;
f *= rn;
x2 *= x;
y2 *= y;
t = y2 - x2;
t /= f;
d += t;
} while (fabsf(t/d) > MACHEPF);
return d;
}
@@ -0,0 +1,8 @@
/* $NetBSD: cephes_subrf.h,v 1.1 2007/08/20 16:01:34 drochner Exp $ */
__attribute__((__visibility__("hidden")))
void _cchshf(float, float *, float *);
__attribute__((__visibility__("hidden")))
float _redupif(float);
__attribute__((__visibility__("hidden")))
float _ctansf(float complex);
@@ -0,0 +1,82 @@
/* $NetBSD: cexp.c,v 1.1 2007/08/20 16:01:34 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cexp>>, <<cexpf>>---complex base-e exponential
INDEX
cexp
INDEX
cexpf
SYNOPSIS
#include <complex.h>
double complex cexp(double complex <[z]>);
float complex cexpf(float complex <[z]>);
DESCRIPTION
These functions compute the complex base-<[e]> exponential of <[z]>.
<<cexpf>> is identical to <<cexp>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
The cexp functions return the complex base-<[e]> exponential value.
PORTABILITY
<<cexp>> and <<cexpf>> are ISO C99
QUICKREF
<<cexp>> and <<cexpf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
cexp(double complex z)
{
double complex w;
double r, x, y;
x = creal(z);
y = cimag(z);
r = exp(x);
w = r * cos(y) + r * sin(y) * I;
return w;
}
@@ -0,0 +1,49 @@
/* $NetBSD: cexpf.c,v 1.1 2007/08/20 16:01:34 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
cexpf(float complex z)
{
float complex w;
float r, x, y;
x = crealf(z);
y = cimagf(z);
r = expf(x);
w = r * cosf(y) + r * sinf(y) * I;
return w;
}
@@ -0,0 +1,60 @@
/* $NetBSD: cimag.c,v 1.2 2010/09/15 16:11:29 christos Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cimag>>, <<cimagf>>, <<cimagl>>---imaginary part
INDEX
cimag
INDEX
cimagf
INDEX
cimagl
SYNOPSIS
#include <complex.h>
double cimag(double complex <[z]>);
float cimagf(float complex <[z]>);
long double cimagl(long double complex <[z]>);
DESCRIPTION
These functions compute the imaginary part of <[z]>.
<<cimagf>> is identical to <<cimag>>, except that it performs
its calculations on <<float complex>>.
<<cimagl>> is identical to <<cimag>>, except that it performs
its calculations on <<long double complex>>.
RETURNS
The cimag* functions return the imaginary part value (as a real).
PORTABILITY
<<cimag>>, <<cimagf>> and <<cimagl>> are ISO C99
QUICKREF
<<cimag>>, <<cimagf>> and <<cimagl>> are ISO C99
*/
#include <complex.h>
#include "fdlibm.h"
double
cimag(double complex z)
{
double_complex w = { .z = z };
return (IMAG_PART(w));
}
@@ -0,0 +1,21 @@
/* $NetBSD: cimagf.c,v 1.2 2010/09/15 16:11:29 christos Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include "fdlibm.h"
float
cimagf(float complex z)
{
float_complex w = { .z = z };
return (IMAG_PART(w));
}
@@ -0,0 +1,91 @@
/* $NetBSD: clog.c,v 1.1 2007/08/20 16:01:35 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<clog>>, <<clogf>>---complex base-e logarithm
INDEX
clog
INDEX
clogf
SYNOPSIS
#include <complex.h>
double complex clog(double complex <[z]>);
float complex clogf(float complex <[z]>);
DESCRIPTION
These functions compute the complex natural (base-<[e]>) logarithm
of <[z]>, with a branch cut along the negative real axis.
<<clogf>> is identical to <<clog>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
@ifnottex
The clog functions return the complex natural logarithm value, in
the range of a strip mathematically unbounded along the real axis
and in the interval [-i*pi , +i*pi] along the imaginary axis.
@end ifnottex
@tex
The clog functions return the complex natural logarithm value, in
the range of a strip mathematically unbounded along the real axis
and in the interval [$-i\pi$, $+i\pi$] along the imaginary axis.
@end tex
PORTABILITY
<<clog>> and <<clogf>> are ISO C99
QUICKREF
<<clog>> and <<clogf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
clog(double complex z)
{
double complex w;
double p, rr;
rr = cabs(z);
p = log(rr);
rr = atan2(cimag(z), creal(z));
w = p + rr * I;
return w;
}
@@ -0,0 +1,49 @@
/* $NetBSD: clogf.c,v 1.1 2007/08/20 16:01:35 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
clogf(float complex z)
{
float complex w;
float p, rr;
rr = cabsf(z);
p = logf(rr);
rr = atan2f(cimagf(z), crealf(z));
w = p + rr * I;
return w;
}
@@ -0,0 +1,56 @@
/* $NetBSD: conj.c,v 1.2 2010/09/15 16:11:29 christos Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<conj>>, <<conjf>>---complex conjugate
INDEX
conj
INDEX
conjf
SYNOPSIS
#include <complex.h>
double complex conj(double complex <[z]>);
float complex conjf(float complex <[z]>);
DESCRIPTION
These functions compute the complex conjugate of <[z]>,
by reversing the sign of its imaginary part.
<<conjf>> is identical to <<conj>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
The conj functions return the complex conjugate value.
PORTABILITY
<<conj>> and <<conjf>> are ISO C99
QUICKREF
<<conj>> and <<conjf>> are ISO C99
*/
#include <complex.h>
#include "fdlibm.h"
double complex
conj(double complex z)
{
double_complex w = { .z = z };
IMAG_PART(w) = -IMAG_PART(w);
return (w.z);
}
@@ -0,0 +1,23 @@
/* $NetBSD: conjf.c,v 1.2 2010/09/15 16:11:29 christos Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include "fdlibm.h"
float complex
conjf(float complex z)
{
float_complex w = { .z = z };
IMAG_PART(w) = -IMAG_PART(w);
return (w.z);
}
@@ -0,0 +1,101 @@
/* $NetBSD: cpow.c,v 1.1 2007/08/20 16:01:35 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cpow>>, <<cpowf>>---complex power
INDEX
cpow
INDEX
cpowf
SYNOPSIS
#include <complex.h>
double complex cpow(double complex <[x]>, double complex <[y]>);
float complex cpowf(float complex <[x]>, float complex <[y]>);
DESCRIPTION
@ifnottex
The cpow functions compute the complex power function x^y
power, with a branch cut for the first parameter along the
negative real axis.
@end ifnottex
@tex
The cpow functions compute the complex power function $x^y$
power, with a branch cut for the first parameter along the
negative real axis.
@end tex
<<cpowf>> is identical to <<cpow>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
The cpow functions return the complex power function value.
PORTABILITY
<<cpow>> and <<cpowf>> are ISO C99
QUICKREF
<<cpow>> and <<cpowf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
cpow(double complex a, double complex z)
{
double complex w;
double x, y, r, theta, absa, arga;
x = creal(z);
y = cimag(z);
absa = cabs(a);
if (absa == 0.0) {
return (0.0 + 0.0 * I);
}
arga = carg(a);
r = pow(absa, x);
theta = x * arga;
if (y != 0.0) {
r = r * exp(-y * arga);
theta = theta + y * log(absa);
}
w = r * cos(theta) + (r * sin(theta)) * I;
return w;
}
@@ -0,0 +1,59 @@
/* $NetBSD: cpowf.c,v 1.1 2007/08/20 16:01:36 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
cpowf(float complex a, float complex z)
{
float complex w;
float x, y, r, theta, absa, arga;
x = crealf(z);
y = cimagf(z);
absa = cabsf(a);
if (absa == 0.0f) {
return (0.0f + 0.0f * I);
}
arga = cargf(a);
r = powf(absa, x);
theta = x * arga;
if (y != 0.0f) {
r = r * expf(-y * arga);
theta = theta + y * logf(absa);
}
w = r * cosf(theta) + (r * sinf(theta)) * I;
return w;
}
@@ -0,0 +1,105 @@
/* $NetBSD: cproj.c,v 1.3 2010/09/20 17:51:38 christos Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<cproj>>, <<cprojf>>--- Riemann sphere projection
INDEX
cproj
INDEX
cprojf
SYNOPSIS
#include <complex.h>
double complex cproj(double complex <[z]>);
float complex cprojf(float complex <[z]>);
DESCRIPTION
These functions compute a projection of <[z]> onto the Riemann
sphere: <[z]> projects to <[z]> except that all complex infinities
(even those with one infinite part and one NaN part) project
to positive infinity on the real axis. If <[z]> has an infinite part,
then <<cproj>>(<[z]>) is equivalent to
INFINITY + I * copysign(0.0, cimag(z))
<<cprojf>> is identical to <<cproj>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
The cproj functions return the value of the projection onto
the Riemann sphere.
PORTABILITY
<<cproj>> and <<cprojf>> are ISO C99
QUICKREF
<<cproj>> and <<cprojf>> are ISO C99
*/
/*__RCSID("$NetBSD: cproj.c,v 1.3 2010/09/20 17:51:38 christos Exp $"); */
#include <complex.h>
#include <math.h>
#include "fdlibm.h"
/*
* cproj(double complex z)
*
* These functions return the value of the projection (not stereographic!)
* onto the Riemann sphere.
*
* z projects to z, except that all complex infinities (even those with one
* infinite part and one NaN part) project to positive infinity on the real axis.
* If z has an infinite part, then cproj(z) shall be equivalent to:
*
* INFINITY + I * copysign(0.0, cimag(z))
*/
double complex
cproj(double complex z)
{
double_complex w = { .z = z };
if (isinf(creal(z)) || isinf(cimag(z))) {
#ifdef __INFINITY
REAL_PART(w) = __INFINITY;
#else
REAL_PART(w) = INFINITY;
#endif
IMAG_PART(w) = copysign(0.0, cimag(z));
}
return (w.z);
}
@@ -0,0 +1,67 @@
/* $NetBSD: cprojf.c,v 1.3 2010/09/20 17:51:38 christos Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*__RCSID("$NetBSD: cprojf.c,v 1.3 2010/09/20 17:51:38 christos Exp $"); */
#include <complex.h>
#include <math.h>
#include "fdlibm.h"
/*
* cprojf(float complex z)
*
* These functions return the value of the projection (not stereographic!)
* onto the Riemann sphere.
*
* z projects to z, except that all complex infinities (even those with one
* infinite part and one NaN part) project to positive infinity on the real axis.
* If z has an infinite part, then cproj(z) shall be equivalent to:
*
* INFINITY + I * copysign(0.0, cimag(z))
*/
float complex
cprojf(float complex z)
{
float_complex w = { .z = z };
if (isinf(crealf(z)) || isinf(cimagf(z))) {
#ifdef __INFINITY
REAL_PART(w) = __INFINITY;
#else
REAL_PART(w) = INFINITY;
#endif
IMAG_PART(w) = copysignf(0.0, cimagf(z));
}
return (w.z);
}
@@ -0,0 +1,60 @@
/* $NetBSD: creal.c,v 1.2 2010/09/15 16:11:29 christos Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<creal>>, <<crealf>>, <<creall>>---real part
INDEX
creal
INDEX
crealf
INDEX
creall
SYNOPSIS
#include <complex.h>
double creal(double complex <[z]>);
float crealf(float complex <[z]>);
double long creall(long double complex <[z]>);
DESCRIPTION
These functions compute the real part of <[z]>.
<<crealf>> is identical to <<creal>>, except that it performs
its calculations on <<float complex>>.
<<creall>> is identical to <<creal>>, except that it performs
its calculations on <<long double complex>>.
RETURNS
The creal* functions return the real part value.
PORTABILITY
<<creal>>, <<crealf>> and <<creall>> are ISO C99
QUICKREF
<<creal>>, <<crealf>> and <<creall>> are ISO C99
*/
#include <complex.h>
#include "fdlibm.h"
double
creal(double complex z)
{
double_complex w = { .z = z };
return (REAL_PART(w));
}
@@ -0,0 +1,21 @@
/* $NetBSD: crealf.c,v 1.2 2010/09/15 16:11:29 christos Exp $ */
/*
* Written by Matthias Drochner <drochner@NetBSD.org>.
* Public domain.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include "fdlibm.h"
float
crealf(float complex z)
{
float_complex w = { .z = z };
return (REAL_PART(w));
}
@@ -0,0 +1,81 @@
/* $NetBSD: csin.c,v 1.1 2007/08/20 16:01:36 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<csin>>, <<csinf>>---complex sine
INDEX
csin
INDEX
csinf
SYNOPSIS
#include <complex.h>
double complex csin(double complex <[z]>);
float complex csinf(float complex <[z]>);
DESCRIPTION
These functions compute the complex sine of <[z]>.
<<csinf>> is identical to <<csin>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
These functions return the complex sine value.
PORTABILITY
<<csin>> and <<csinf>> are ISO C99
QUICKREF
<<csin>> and <<csinf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
#include "cephes_subr.h"
double complex
csin(double complex z)
{
double complex w;
double ch, sh;
_cchsh(cimag(z), &ch, &sh);
w = sin(creal(z)) * ch + (cos(creal(z)) * sh) * I;
return w;
}
@@ -0,0 +1,48 @@
/* $NetBSD: csinf.c,v 1.1 2007/08/20 16:01:36 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#include "cephes_subrf.h"
float complex
csinf(float complex z)
{
float complex w;
float ch, sh;
_cchshf(cimagf(z), &ch, &sh);
w = sinf(crealf(z)) * ch + (cosf(crealf(z)) * sh) * I;
return w;
}
@@ -0,0 +1,80 @@
/* $NetBSD: csinh.c,v 1.1 2007/08/20 16:01:36 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<csinh>>, <<csinhf>>---complex hyperbolic sine
INDEX
csinh
INDEX
csinhf
SYNOPSIS
#include <complex.h>
double complex csinh(double complex <[z]>);
float complex csinhf(float complex <[z]>);
DESCRIPTION
These functions compute the complex hyperbolic sine of <[z]>.
<<ccoshf>> is identical to <<ccosh>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
These functions return the complex hyperbolic sine value.
PORTABILITY
<<csinh>> and <<csinhf>> are ISO C99
QUICKREF
<<csinh>> and <<csinhf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
csinh(double complex z)
{
double complex w;
double x, y;
x = creal(z);
y = cimag(z);
w = sinh(x) * cos(y) + (cosh(x) * sin(y)) * I;
return w;
}
@@ -0,0 +1,48 @@
/* $NetBSD: csinhf.c,v 1.1 2007/08/20 16:01:37 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
csinhf(float complex z)
{
float complex w;
float x, y;
x = crealf(z);
y = cimagf(z);
w = sinhf(x) * cosf(y) + (coshf(x) * sinf(y)) * I;
return w;
}
@@ -0,0 +1,137 @@
/* $NetBSD: csqrt.c,v 1.1 2007/08/20 16:01:37 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<csqrt>>, <<csqrtf>>---complex square root
INDEX
csqrt
INDEX
csqrtf
SYNOPSIS
#include <complex.h>
double complex csqrt(double complex <[z]>);
float complex csqrtf(float complex <[z]>);
DESCRIPTION
These functions compute the complex square root of <[z]>, with
a branch cut along the negative real axis.
<<csqrtf>> is identical to <<csqrt>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
The csqrt functions return the complex square root value, in
the range of the right halfplane (including the imaginary axis).
PORTABILITY
<<csqrt>> and <<csqrtf>> are ISO C99
QUICKREF
<<csqrt>> and <<csqrtf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
csqrt(double complex z)
{
double complex w;
double x, y, r, t, scale;
x = creal (z);
y = cimag (z);
if (y == 0.0) {
if (x == 0.0) {
w = 0.0 + y * I;
} else {
r = fabs(x);
r = sqrt(r);
if (x < 0.0) {
w = 0.0 + r * I;
} else {
w = r + y * I;
}
}
return w;
}
if (x == 0.0) {
r = fabs(y);
r = sqrt(0.5 * r);
if (y > 0)
w = r + r * I;
else
w = r - r * I;
return w;
}
/* Rescale to avoid internal overflow or underflow. */
if ((fabs(x) > 4.0) || (fabs(y) > 4.0)) {
x *= 0.25;
y *= 0.25;
scale = 2.0;
} else {
#if 1
x *= 1.8014398509481984e16; /* 2^54 */
y *= 1.8014398509481984e16;
scale = 7.450580596923828125e-9; /* 2^-27 */
#else
x *= 4.0;
y *= 4.0;
scale = 0.5;
#endif
}
w = x + y * I;
r = cabs(w);
if (x > 0) {
t = sqrt(0.5 * r + 0.5 * x);
r = scale * fabs((0.5 * y) / t );
t *= scale;
} else {
r = sqrt(0.5 * r - 0.5 * x);
t = scale * fabs((0.5 * y) / r);
r *= scale;
}
if (y < 0)
w = t - r * I;
else
w = t + r * I;
return w;
}
@@ -0,0 +1,102 @@
/* $NetBSD: csqrtf.c,v 1.1 2007/08/20 16:01:37 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
csqrtf(float complex z)
{
float complex w;
float x, y, r, t, scale;
x = crealf (z);
y = cimagf (z);
if (y == 0.0f) {
if (x < 0.0f) {
w = 0.0f + sqrtf(-x) * I;
return w;
} else if (x == 0.0f) {
return (0.0f + y * I);
} else {
w = sqrtf(x) + y * I;
return w;
}
}
if (x == 0.0f) {
r = fabsf(y);
r = sqrtf(0.5f * r);
if (y > 0)
w = r + r * I;
else
w = r - r * I;
return w;
}
/* Rescale to avoid internal overflow or underflow. */
if ((fabsf(x) > 4.0f) || (fabsf(y) > 4.0f)) {
x *= 0.25f;
y *= 0.25f;
scale = 2.0f;
} else {
#if 1
x *= 6.7108864e7f; /* 2^26 */
y *= 6.7108864e7f;
scale = 1.220703125e-4f; /* 2^-13 */
#else
x *= 4.0f;
y *= 4.0f;
scale = 0.5f;
#endif
}
w = x + y * I;
r = cabsf(w);
if( x > 0 ) {
t = sqrtf(0.5f * r + 0.5f * x);
r = scale * fabsf((0.5f * y) / t);
t *= scale;
} else {
r = sqrtf(0.5f * r - 0.5f * x);
t = scale * fabsf((0.5f * y) / r);
r *= scale;
}
if (y < 0)
w = t - r * I;
else
w = t + r * I;
return w;
}
@@ -0,0 +1,91 @@
/* $NetBSD: ctan.c,v 1.1 2007/08/20 16:01:37 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<ctan>>, <<ctanf>>---complex tangent
INDEX
ctan
INDEX
ctanf
SYNOPSIS
#include <complex.h>
double complex ctan(double complex <[z]>);
float complex ctanf(float complex <[z]>);
DESCRIPTION
These functions compute the complex tangent of <[z]>.
<<ctanf>> is identical to <<ctan>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
These functions return the complex tangent value.
PORTABILITY
<<ctan>> and <<ctanf>> are ISO C99
QUICKREF
<<ctan>> and <<ctanf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
#include "cephes_subr.h"
double complex
ctan(double complex z)
{
double complex w;
double d;
d = cos(2.0 * creal(z)) + cosh(2.0 * cimag(z));
if (fabs(d) < 0.25)
d = _ctans(z);
if (d == 0.0) {
/* mtherr ("ctan", OVERFLOW); */
w = HUGE_VAL + HUGE_VAL * I;
return w;
}
w = sin(2.0 * creal(z)) / d + (sinh(2.0 * cimag(z)) / d) * I;
return w;
}
@@ -0,0 +1,58 @@
/* $NetBSD: ctanf.c,v 1.1 2007/08/20 16:01:38 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
#include "cephes_subrf.h"
float complex
ctanf(float complex z)
{
float complex w;
float d;
d = cosf(2.0f * crealf(z)) + coshf(2.0f * cimagf(z));
if (fabsf(d) < 0.25f)
d = _ctansf(z);
if (d == 0.0f) {
/* mtherr ("ctan", OVERFLOW); */
w = HUGE_VALF + HUGE_VALF * I;
return w;
}
w = sinf(2.0f * crealf(z)) / d + (sinhf(2.0f * cimagf(z)) / d) * I;
return w;
}
@@ -0,0 +1,83 @@
/* $NetBSD: ctanh.c,v 1.1 2007/08/20 16:01:38 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
/*
FUNCTION
<<ctanh>>, <<ctanf>>---complex hyperbolic tangent
INDEX
ctanh
INDEX
ctanhf
SYNOPSIS
#include <complex.h>
double complex ctanh(double complex <[z]>);
float complex ctanhf(float complex <[z]>);
DESCRIPTION
These functions compute the complex hyperbolic tangent of <[z]>.
<<ctanhf>> is identical to <<ctanh>>, except that it performs
its calculations on <<floats complex>>.
RETURNS
These functions return the complex hyperbolic tangent value.
PORTABILITY
<<ctanh>> and <<ctanhf>> are ISO C99
QUICKREF
<<ctanh>> and <<ctanhf>> are ISO C99
*/
#include <complex.h>
#include <math.h>
double complex
ctanh(double complex z)
{
double complex w;
double x, y, d;
x = creal(z);
y = cimag(z);
d = cosh(2.0 * x) + cos(2.0 * y);
w = sinh(2.0 * x) / d + (sin(2.0 * y) / d) * I;
return w;
}
@@ -0,0 +1,50 @@
/* $NetBSD: ctanhf.c,v 1.1 2007/08/20 16:01:38 drochner Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software written by Stephen L. Moshier.
* It is redistributed by the NetBSD Foundation by permission of the author.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* imported and modified include for newlib 2010/10/03
* Marco Atzeri <marco_atzeri@yahoo.it>
*/
#include <complex.h>
#include <math.h>
float complex
ctanhf(float complex z)
{
float complex w;
float x, y, d;
x = crealf(z);
y = cimagf(z);
d = coshf(2.0f * x) + cosf(2.0f * y);
w = sinhf(2.0f * x) / d + (sinf(2.0f * y) / d) * I;
return w;
}
@@ -0,0 +1,17 @@
#ifndef __MLIBC_FDLIBM_H
#define __MLIBC_FDLIBM_H
#define REAL_PART(z) ((z).parts[0])
#define IMAG_PART(z) ((z).parts[1])
typedef union {
float complex z;
float parts[2];
} float_complex;
typedef union {
double complex z;
double parts[2];
} double_complex;
#endif
@@ -0,0 +1,326 @@
#include <ctype.h>
#include <wctype.h>
#include <bits/ensure.h>
#include <mlibc/charset.hpp>
// --------------------------------------------------------------------------------------
// char ctype functions.
// --------------------------------------------------------------------------------------
int isalpha(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_alpha(cp);
}
int isdigit(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_digit(cp);
}
int isxdigit(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_xdigit(cp);
}
int isalnum(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_alnum(cp);
}
int ispunct(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_punct(cp);
}
int isgraph(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_graph(cp);
}
int isblank(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_blank(cp);
}
int isspace(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_space(cp);
}
int isprint(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_print(cp);
}
int islower(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_lower(cp);
}
int isupper(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_upper(cp);
}
int iscntrl(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::generic_is_control(cp);
}
int isascii(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return cp <= 0x7F;
}
// --------------------------------------------------------------------------------------
// wchar_t ctype functions.
// --------------------------------------------------------------------------------------
int iswalpha(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_alpha(cp);
}
int iswdigit(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_digit(cp);
}
int iswxdigit(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_xdigit(cp);
}
int iswalnum(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_alnum(cp);
}
int iswpunct(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_punct(cp);
}
int iswgraph(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_graph(cp);
}
int iswblank(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_blank(cp);
}
int iswspace(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_space(cp);
}
int iswprint(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_print(cp);
}
int iswlower(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_lower(cp);
}
int iswupper(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::current_charset()->is_upper(cp);
}
int iswcntrl(wint_t nc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return 0;
return mlibc::generic_is_control(cp);
}
// --------------------------------------------------------------------------------------
// iswctype functions.
// --------------------------------------------------------------------------------------
namespace {
enum {
ct_null,
ct_alnum,
ct_alpha,
ct_blank,
ct_cntrl,
ct_digit,
ct_graph,
ct_lower,
ct_print,
ct_punct,
ct_space,
ct_upper,
ct_xdigit,
ct_count
};
} // namespace
wctype_t wctype(const char *cs) {
frg::string_view s{cs};
if(s == "alnum") return ct_alnum;
if(s == "alpha") return ct_alpha;
if(s == "blank") return ct_blank;
if(s == "cntrl") return ct_cntrl;
if(s == "digit") return ct_digit;
if(s == "graph") return ct_graph;
if(s == "lower") return ct_lower;
if(s == "print") return ct_print;
if(s == "punct") return ct_punct;
if(s == "space") return ct_space;
if(s == "upper") return ct_upper;
if(s == "xdigit") return ct_xdigit;
mlibc::infoLogger() << "mlibc: wctype(\"" << cs << "\") is not supported" << frg::endlog;
return ct_null;
}
int iswctype(wint_t wc, wctype_t type) {
switch (type) {
case ct_alnum:
return iswalnum(wc);
case ct_alpha:
return iswalpha(wc);
case ct_blank:
return iswblank(wc);
case ct_cntrl:
return iswcntrl(wc);
case ct_digit:
return iswdigit(wc);
case ct_graph:
return iswgraph(wc);
case ct_lower:
return iswlower(wc);
case ct_print:
return iswprint(wc);
case ct_punct:
return iswpunct(wc);
case ct_space:
return iswspace(wc);
case ct_upper:
return iswupper(wc);
case ct_xdigit:
return iswxdigit(wc);
}
return 0;
}
// --------------------------------------------------------------------------------------
// char conversion functions.
// --------------------------------------------------------------------------------------
int tolower(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return nc;
return mlibc::current_charset()->to_lower(cp);
}
int toupper(int nc) {
auto cc = mlibc::current_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(nc, cp); e != mlibc::charcode_error::null)
return nc;
return mlibc::current_charset()->to_upper(cp);
}
// --------------------------------------------------------------------------------------
// wchar_t conversion functions.
// --------------------------------------------------------------------------------------
wint_t towlower(wint_t wc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(wc, cp); e != mlibc::charcode_error::null)
return wc;
return mlibc::current_charset()->to_lower(cp);
}
wint_t towupper(wint_t wc) {
auto cc = mlibc::platform_wide_charcode();
mlibc::codepoint cp;
if(auto e = cc->promote(wc, cp); e != mlibc::charcode_error::null)
return wc;
return mlibc::current_charset()->to_upper(cp);
}
@@ -0,0 +1,168 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <bits/ensure.h>
#include <mlibc/allocator.hpp>
#include <mlibc/debug.hpp>
#include <frg/string.hpp>
#include <frg/vector.hpp>
namespace {
char *empty_environment[] = { nullptr };
} // namespace
char **environ = empty_environment;
namespace {
size_t find_environ_index(frg::string_view name) {
for(size_t i = 0; environ[i]; i++) {
frg::string_view view{environ[i]};
size_t s = view.find_first('=');
if(s == size_t(-1)) {
mlibc::infoLogger() << "mlibc: environment string \""
<< frg::escape_fmt{view.data(), view.size()}
<< "\" does not contain an equals sign (=)" << frg::endlog;
continue;
}
if(view.sub_string(0, s) == name)
return i;
}
return -1;
}
// Environment vector that is mutated by putenv() and setenv().
// Cannot be global as it is accessed during library initialization.
frg::vector<char *, MemoryAllocator> &get_vector() {
static frg::vector<char *, MemoryAllocator> vector{getAllocator()};
return vector;
}
void update_vector() {
auto &vector = get_vector();
if(environ == vector.data())
return;
// If the environ variable was changed, we copy the environment.
// Note that we must only copy the pointers but not the strings themselves!
vector.clear();
for(size_t i = 0; environ[i]; i++)
vector.push(environ[i]);
vector.push(nullptr);
environ = vector.data();
}
void assign_variable(frg::string_view name, const char *string, bool overwrite) {
auto &vector = get_vector();
__ensure(environ == vector.data());
auto k = find_environ_index(name);
if(k != size_t(-1)) {
if(overwrite)
vector[k] = const_cast<char *>(string);
}else{
// Last pointer of environ must always be a null delimiter.
__ensure(!vector.back());
vector.back() = const_cast<char *>(string);
vector.push(nullptr);
}
// push() might have re-allocated the vector.
environ = vector.data();
}
void unassign_variable(frg::string_view name) {
auto &vector = get_vector();
__ensure(environ == vector.data());
auto k = find_environ_index(name);
if(k == size_t(-1))
return;
// Last pointer of environ must always be a null delimiter.
__ensure(vector.size() >= 2 && !vector.back());
std::swap(vector[k], vector[vector.size() - 2]);
vector.pop();
vector.back() = nullptr;
// pop() might have re-allocated the vector.
environ = vector.data();
}
} // anonymous namespace
char *getenv(const char *name) {
auto k = find_environ_index(name);
if(k == size_t(-1))
return nullptr;
frg::string_view view{environ[k]};
size_t s = view.find_first('=');
__ensure(s != size_t(-1));
return const_cast<char *>(view.data() + s + 1);
}
namespace mlibc {
int putenv(char *string) {
frg::string_view view{string};
size_t s = view.find_first('=');
if(s == size_t(-1)) {
// GLIBC EXTENSION
update_vector();
unassign_variable(string);
return 0;
}
update_vector();
assign_variable(view.sub_string(0, s), string, true);
return 0;
}
} // namespace mlibc
#if __MLIBC_POSIX_OPTION
int putenv(char *string) {
return mlibc::putenv(string);
}
int setenv(const char *name, const char *value, int overwrite) {
frg::string_view view{name};
size_t s = view.find_first('=');
if(s != size_t(-1)) {
mlibc::infoLogger() << "mlibc: environment variable \""
<< frg::escape_fmt{view.data(), view.size()} << "\" contains an equals sign"
<< frg::endlog;
errno = EINVAL;
return -1;
}
// We never free strings here. TODO: Reuse them?
char *string;
__ensure(asprintf(&string, "%s=%s", name, value) > 0);
__ensure(string);
update_vector();
assign_variable(name, string, overwrite);
return 0;
}
int unsetenv(const char *name) {
update_vector();
unassign_variable(name);
return 0;
}
int clearenv(void) {
auto vector = get_vector();
vector.clear();
update_vector();
return 0;
}
#endif /* __MLIBC_POSIX_OPTION */
@@ -0,0 +1,12 @@
#include <errno.h>
int __thread __mlibc_errno;
char *program_invocation_name = nullptr;
char *program_invocation_short_name = nullptr;
extern char *__progname __attribute__((__weak__, __alias__("program_invocation_short_name")));
extern char *__progname_full __attribute__((__weak__, __alias__("program_invocation_name")));
int *__errno_location() {
return &__mlibc_errno;
}
@@ -0,0 +1,43 @@
#include <bits/ensure.h>
#include <fenv.h>
// The functions that are not in this file but are defined in the header
// are implemented like musl does in assembly.
extern "C" __attribute__((__visibility__("hidden"))) int __fesetround(int);
int fegetexceptflag(fexcept_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
int feholdexcept(fenv_t *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
int fesetexceptflag(const fexcept_t *, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
int fesetround(int r) {
if (r != FE_TONEAREST
#ifdef FE_DOWNWARD
&& r != FE_DOWNWARD
#endif
#ifdef FE_UPWARD
&& r != FE_UPWARD
#endif
#ifdef FE_TOWARDZERO
&& r != FE_TOWARDZERO
#endif
)
return -1;
return __fesetround(r);
}
int feupdateenv(const fenv_t *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
@@ -0,0 +1,750 @@
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#if __MLIBC_GLIBC_OPTION
#include <stdio_ext.h>
#endif
#include <bits/ensure.h>
#include <mlibc/debug.hpp>
#include <abi-bits/fcntl.h>
#include <frg/allocation.hpp>
#include <frg/mutex.hpp>
#include <mlibc/allocator.hpp>
#include <mlibc/file-io.hpp>
#include <mlibc/ansi-sysdeps.hpp>
#include <mlibc/lock.hpp>
namespace mlibc {
// --------------------------------------------------------------------------------------
// abstract_file implementation.
// --------------------------------------------------------------------------------------
namespace {
using file_list = frg::intrusive_list<
abstract_file,
frg::locate_member<
abstract_file,
frg::default_list_hook<abstract_file>,
&abstract_file::_list_hook
>
>;
// Useful when debugging the FILE implementation.
constexpr bool globallyDisableBuffering = false;
// The maximum number of characters we permit the user to ungetc.
constexpr size_t ungetBufferSize = 8;
// List of files that will be flushed before exit().
file_list &global_file_list() {
static frg::eternal<file_list> list;
return list.get();
};
} // namespace
// For pipe-like streams (seek returns ESPIPE), we need to make sure
// that the buffer only ever contains all-dirty or all-clean data.
// Regarding _type and _bufmode:
// As we might construct FILE objects for FDs that are not actually
// open (e.g. for std{in,out,err}), we defer the type determination and cache the result.
abstract_file::abstract_file(void (*do_dispose)(abstract_file *))
: _type{stream_type::unknown}, _bufmode{buffer_mode::unknown}, _do_dispose{do_dispose} {
// TODO: For __fwriting to work correctly, set the __io_mode to 1 if the write is write-only.
__buffer_ptr = nullptr;
__unget_ptr = nullptr;
__buffer_size = 4096;
__offset = 0;
__io_offset = 0;
__valid_limit = 0;
__dirty_begin = 0;
__dirty_end = 0;
__io_mode = 0;
__status_bits = 0;
global_file_list().push_back(this);
}
abstract_file::~abstract_file() {
if(__dirty_begin != __dirty_end)
mlibc::infoLogger() << "mlibc warning: File is not flushed before destruction"
<< frg::endlog;
if(__buffer_ptr)
getAllocator().free(__buffer_ptr - ungetBufferSize);
auto it = global_file_list().iterator_to(this);
global_file_list().erase(it);
}
void abstract_file::dispose() {
if(!_do_dispose)
return;
_do_dispose(this);
}
// Note that read() and write() are asymmetric:
// While read() can trigger a write-back, write() can never trigger a read-ahead().
// This peculiarity is reflected in their code.
int abstract_file::read(char *buffer, size_t max_size, size_t *actual_size) {
__ensure(max_size);
if(_init_bufmode())
return -1;
size_t unget_length = 0;
if (__unget_ptr != __buffer_ptr) {
unget_length = frg::min(max_size, (size_t)(__buffer_ptr - __unget_ptr));
memcpy(buffer, __unget_ptr, unget_length);
__unget_ptr += unget_length;
buffer += unget_length;
max_size -= unget_length;
if (max_size == 0) {
*actual_size = unget_length;
return 0;
}
}
if(globallyDisableBuffering || _bufmode == buffer_mode::no_buffer) {
size_t io_size;
if(int e = io_read(buffer, max_size, &io_size); e) {
__status_bits |= __MLIBC_ERROR_BIT;
return e;
}
if(!io_size)
__status_bits |= __MLIBC_EOF_BIT;
*actual_size = io_size + unget_length;
return 0;
}
// Ensure correct buffer type for pipe-like streams.
// TODO: In order to support pipe-like streams we need to write-back the buffer.
if(__io_mode && __valid_limit)
mlibc::panicLogger() << "mlibc: Cannot read-write to same pipe-like stream"
<< frg::endlog;
__io_mode = 0;
// Clear the buffer, then buffer new data.
if(__offset == __valid_limit) {
// TODO: We only have to write-back/reset if __valid_limit reaches the buffer end.
if(int e = _write_back(); e)
return e;
if(int e = _reset(); e)
return e;
// Perform a read-ahead.
_ensure_allocation();
size_t io_size;
if(int e = io_read(__buffer_ptr, __buffer_size, &io_size); e) {
__status_bits |= __MLIBC_ERROR_BIT;
return e;
}
if(!io_size) {
__status_bits |= __MLIBC_EOF_BIT;
*actual_size = 0;
return 0;
}
__io_offset = io_size;
__valid_limit = io_size;
}
// Return data from the buffer.
__ensure(__offset < __valid_limit);
auto chunk = frg::min(size_t(__valid_limit - __offset), max_size);
memcpy(buffer, __buffer_ptr + __offset, chunk);
__offset += chunk;
*actual_size = chunk + unget_length;
return 0;
}
int abstract_file::write(const char *buffer, size_t max_size, size_t *actual_size) {
__ensure(max_size);
if(_init_bufmode())
return -1;
if(globallyDisableBuffering || _bufmode == buffer_mode::no_buffer) {
// As we do not buffer, nothing can be dirty.
__ensure(__dirty_begin == __dirty_end);
size_t io_size;
if(int e = io_write(buffer, max_size, &io_size); e) {
__status_bits |= __MLIBC_ERROR_BIT;
return e;
}
*actual_size = io_size;
return 0;
}
// Flush the buffer if necessary.
if(__offset == __buffer_size) {
if(int e = _write_back(); e)
return e;
if(int e = _reset(); e)
return e;
}
// Ensure correct buffer type for pipe-like streams.
// TODO: We could full support pipe-like files
// by ungetc()ing all data before a write happens,
// however, for now we just report an error.
if(!__io_mode && __valid_limit) // TODO: Only check this for pipe-like streams.
mlibc::panicLogger() << "mlibc: Cannot read-write to same pipe-like stream"
<< frg::endlog;
__io_mode = 1;
__ensure(__offset < __buffer_size);
auto chunk = frg::min(__buffer_size - __offset, max_size);
// Line-buffered streams perform I/O on full lines.
bool flush_line = false;
if(_bufmode == buffer_mode::line_buffer) {
auto nl = reinterpret_cast<char *>(memchr(buffer, '\n', chunk));
if(nl) {
chunk = nl + 1 - buffer;
flush_line = true;
}
}
__ensure(chunk);
// Buffer data (without necessarily performing I/O).
_ensure_allocation();
memcpy(__buffer_ptr + __offset, buffer, chunk);
if(__dirty_begin != __dirty_end) {
__dirty_begin = frg::min(__dirty_begin, __offset);
__dirty_end = frg::max(__dirty_end, __offset + chunk);
}else{
__dirty_begin = __offset;
__dirty_end = __offset + chunk;
}
__valid_limit = frg::max(__offset + chunk, __valid_limit);
__offset += chunk;
// Flush line-buffered streams.
if(flush_line) {
if(_write_back())
return -1;
}
*actual_size = chunk;
return 0;
}
int abstract_file::unget(char c) {
if (!__unget_ptr) {
// This can happen if the file is unbuffered, but we still need
// a space to store ungetc'd data.
__ensure(!__buffer_ptr);
_ensure_allocation();
__ensure(__unget_ptr);
}
if ((size_t)(__buffer_ptr - __unget_ptr) + 1 > ungetBufferSize)
return EOF;
else {
*(--__unget_ptr) = c;
return c;
}
}
int abstract_file::update_bufmode(buffer_mode mode) {
// setvbuf() has undefined behavior if I/O has been performed.
__ensure(__dirty_begin == __dirty_end
&& "update_bufmode() must only be called before performing I/O");
_bufmode = mode;
return 0;
}
void abstract_file::purge() {
__offset = 0;
__io_offset = 0;
__valid_limit = 0;
__dirty_end = __dirty_begin;
__unget_ptr = __buffer_ptr;
}
int abstract_file::flush() {
if (__dirty_end != __dirty_begin) {
if (int e = _write_back(); e)
return e;
}
if (int e = _save_pos(); e)
return e;
purge();
return 0;
}
int abstract_file::tell(off_t *current_offset) {
off_t seek_offset;
if(int e = io_seek(0, SEEK_CUR, &seek_offset); e)
return e;
*current_offset = seek_offset
+ (off_t(__offset) - off_t(__io_offset))
+ (off_t(__unget_ptr) - off_t(__buffer_ptr));
return 0;
}
int abstract_file::seek(off_t offset, int whence) {
if(int e = _write_back(); e)
return e;
off_t new_offset;
if(whence == SEEK_CUR) {
auto seek_offset = offset + (off_t(__offset) - off_t(__io_offset));
if(int e = io_seek(seek_offset, whence, &new_offset); e) {
__status_bits |= __MLIBC_ERROR_BIT;
return e;
}
}else{
__ensure(whence == SEEK_SET || whence == SEEK_END);
if(int e = io_seek(offset, whence, &new_offset); e) {
__status_bits |= __MLIBC_ERROR_BIT;
return e;
}
}
// We just forget the current buffer.
// TODO: If the seek is "small", we can just modify our internal offset.
purge();
return 0;
}
int abstract_file::_init_type() {
if(_type != stream_type::unknown)
return 0;
if(int e = determine_type(&_type); e)
return e;
__ensure(_type != stream_type::unknown);
return 0;
}
int abstract_file::_init_bufmode() {
if(_bufmode != buffer_mode::unknown)
return 0;
if(determine_bufmode(&_bufmode))
return -1;
__ensure(_bufmode != buffer_mode::unknown);
return 0;
}
int abstract_file::_write_back() {
if(int e = _init_type(); e)
return e;
if(__dirty_begin == __dirty_end)
return 0;
// For non-pipe streams, first do a seek to reset the
// I/O position to zero, then do a write().
if(_type == stream_type::file_like) {
if(__io_offset != __dirty_begin) {
__ensure(__dirty_begin - __io_offset > 0);
off_t new_offset;
if(int e = io_seek(off_t(__dirty_begin) - off_t(__io_offset), SEEK_CUR, &new_offset); e)
return e;
__io_offset = __dirty_begin;
}
}else{
__ensure(_type == stream_type::pipe_like);
__ensure(__io_offset == __dirty_begin);
}
// Now, we are in the correct position to write-back everything.
while(__io_offset < __dirty_end) {
size_t io_size;
if(int e = io_write(__buffer_ptr + __io_offset, __dirty_end - __io_offset, &io_size); e) {
__status_bits |= __MLIBC_ERROR_BIT;
return e;
}
__ensure(io_size > 0 && "io_write() is expected to always write at least one byte");
__io_offset += io_size;
__dirty_begin += io_size;
}
return 0;
}
int abstract_file::_save_pos() {
if (int e = _init_type(); e)
return e;
if (int e = _init_bufmode(); e)
return e;
if (_type == stream_type::file_like && _bufmode != buffer_mode::no_buffer) {
off_t new_offset;
auto seek_offset = (off_t(__offset) - off_t(__io_offset));
if (int e = io_seek(seek_offset, SEEK_CUR, &new_offset); e) {
__status_bits |= __MLIBC_ERROR_BIT;
mlibc::infoLogger() << "hit io_seek() error " << e << frg::endlog;
return e;
}
return 0;
}
return 0; // nothing to do for the rest
}
int abstract_file::_reset() {
if(int e = _init_type(); e)
return e;
// For pipe-like files, we must not forget already read data.
// TODO: Report this error to the user.
if(_type == stream_type::pipe_like)
__ensure(__offset == __valid_limit);
__ensure(__dirty_begin == __dirty_end);
__offset = 0;
__io_offset = 0;
__valid_limit = 0;
return 0;
}
// This may still be called when buffering is disabled, for ungetc.
void abstract_file::_ensure_allocation() {
if(__buffer_ptr)
return;
auto ptr = getAllocator().allocate(__buffer_size + ungetBufferSize);
__buffer_ptr = reinterpret_cast<char *>(ptr) + ungetBufferSize;
__unget_ptr = __buffer_ptr;
}
// --------------------------------------------------------------------------------------
// fd_file implementation.
// --------------------------------------------------------------------------------------
fd_file::fd_file(int fd, void (*do_dispose)(abstract_file *), bool force_unbuffered)
: abstract_file{do_dispose}, _fd{fd}, _force_unbuffered{force_unbuffered} { }
int fd_file::fd() {
return _fd;
}
int fd_file::close() {
if(__dirty_begin != __dirty_end)
mlibc::infoLogger() << "mlibc warning: File is not flushed before closing"
<< frg::endlog;
if(int e = mlibc::sys_close(_fd); e)
return e;
return 0;
}
int fd_file::reopen(const char *path, const char *mode) {
int mode_flags = parse_modestring(mode);
int fd;
if(int e = sys_open(path, mode_flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, &fd); e) {
return e;
}
flush();
close();
getAllocator().deallocate(__buffer_ptr, __buffer_size + ungetBufferSize);
__buffer_ptr = nullptr;
__unget_ptr = nullptr;
__buffer_size = 4096;
_reset();
_fd = fd;
if(mode_flags & O_APPEND) {
seek(0, SEEK_END);
}
return 0;
}
int fd_file::determine_type(stream_type *type) {
off_t offset;
int e = mlibc::sys_seek(_fd, 0, SEEK_CUR, &offset);
if(!e) {
*type = stream_type::file_like;
return 0;
}else if(e == ESPIPE) {
*type = stream_type::pipe_like;
return 0;
}else{
return e;
}
}
int fd_file::determine_bufmode(buffer_mode *mode) {
// When isatty() is not implemented, we fall back to the safest default (no buffering).
if(!mlibc::sys_isatty) {
MLIBC_MISSING_SYSDEP();
*mode = buffer_mode::no_buffer;
return 0;
}
if(_force_unbuffered) {
*mode = buffer_mode::no_buffer;
return 0;
}
if(int e = mlibc::sys_isatty(_fd); !e) {
*mode = buffer_mode::line_buffer;
return 0;
}else if(e == ENOTTY) {
*mode = buffer_mode::full_buffer;
return 0;
}else{
mlibc::infoLogger() << "mlibc: sys_isatty() failed while determining whether"
" stream is interactive" << frg::endlog;
return -1;
}
}
int fd_file::io_read(char *buffer, size_t max_size, size_t *actual_size) {
ssize_t s;
if(int e = mlibc::sys_read(_fd, buffer, max_size, &s); e)
return e;
*actual_size = s;
return 0;
}
int fd_file::io_write(const char *buffer, size_t max_size, size_t *actual_size) {
ssize_t s;
if(int e = mlibc::sys_write(_fd, buffer, max_size, &s); e)
return e;
*actual_size = s;
return 0;
}
int fd_file::io_seek(off_t offset, int whence, off_t *new_offset) {
if(int e = mlibc::sys_seek(_fd, offset, whence, new_offset); e)
return e;
return 0;
}
int fd_file::parse_modestring(const char *mode) {
// Consume the first char; this must be 'r', 'w' or 'a'.
int flags = 0;
bool has_plus = strchr(mode, '+');
if (*mode == 'r') {
if (has_plus) {
flags = O_RDWR;
} else {
flags = O_RDONLY;
}
} else if (*mode == 'w') {
if (has_plus) {
flags = O_RDWR;
} else {
flags = O_WRONLY;
}
flags |= O_CREAT | O_TRUNC;
} else if (*mode == 'a') {
if (has_plus) {
flags = O_APPEND | O_RDWR;
} else {
flags = O_APPEND | O_WRONLY;
}
flags |= O_CREAT;
} else {
mlibc::infoLogger() << "Illegal fopen() mode '" << *mode << "'" << frg::endlog;
}
mode += 1;
// Consume additional flags.
while (*mode) {
if (*mode == '+') {
mode++; // This is already handled above.
} else if (*mode == 'b') {
mode++; // mlibc assumes that there is no distinction between text and binary.
} else if (*mode == 'e') {
flags |= O_CLOEXEC;
mode++;
} else if (*mode == 'x') {
flags |= O_EXCL;
mode++;
} else {
mlibc::infoLogger() << "Illegal fopen() flag '" << mode << "'" << frg::endlog;
mode++;
}
}
return flags;
}
} // namespace mlibc
namespace {
mlibc::fd_file stdin_file{0};
mlibc::fd_file stdout_file{1};
mlibc::fd_file stderr_file{2, nullptr, true};
struct stdio_guard {
stdio_guard() { }
~stdio_guard() {
// Only flush the files but do not close them.
for(auto it : mlibc::global_file_list()) {
if(int e = it->flush(); e)
mlibc::infoLogger() << "mlibc warning: Failed to flush file before exit()"
<< frg::endlog;
}
}
} global_stdio_guard;
} // namespace
FILE *stderr = &stderr_file;
FILE *stdin = &stdin_file;
FILE *stdout = &stdout_file;
int fileno_unlocked(FILE *file_base) {
auto file = static_cast<mlibc::fd_file *>(file_base);
return file->fd();
}
int fileno(FILE *file_base) {
auto file = static_cast<mlibc::fd_file *>(file_base);
frg::unique_lock lock(file->_lock);
return fileno_unlocked(file_base);
}
FILE *fopen(const char *path, const char *mode) {
int flags = mlibc::fd_file::parse_modestring(mode);
int fd;
if(int e = mlibc::sys_open(path, flags, 0666, &fd); e) {
errno = e;
return nullptr;
}
return frg::construct<mlibc::fd_file>(getAllocator(), fd,
mlibc::file_dispose_cb<mlibc::fd_file>);
}
int fclose(FILE *file_base) {
auto file = static_cast<mlibc::abstract_file *>(file_base);
int e = 0;
if(file->flush())
e = EOF;
if(file->close())
e = EOF;
file->dispose();
return e;
}
int fseek(FILE *file_base, long offset, int whence) {
auto file = static_cast<mlibc::abstract_file *>(file_base);
frg::unique_lock lock(file->_lock);
if(int e = file->seek(offset, whence); e) {
errno = e;
return -1;
}
return 0;
}
long ftell(FILE *file_base) {
auto file = static_cast<mlibc::abstract_file *>(file_base);
frg::unique_lock lock(file->_lock);
off_t current_offset;
if(int e = file->tell(&current_offset); e) {
errno = e;
return -1;
}
return current_offset;
}
int fflush_unlocked(FILE *file_base) {
if(file_base == nullptr) {
// Only flush the files but do not close them.
for(auto it : mlibc::global_file_list()) {
if(int e = it->flush(); e)
mlibc::infoLogger() << "mlibc warning: Failed to flush file"
<< frg::endlog;
}
return 0;
}
auto file = static_cast<mlibc::abstract_file *>(file_base);
if(file->flush())
return EOF;
return 0;
}
int fflush(FILE *file_base) {
if(file_base == nullptr) {
// Only flush the files but do not close them.
for(auto it : mlibc::global_file_list()) {
frg::unique_lock lock(it->_lock);
if(int e = it->flush(); e)
mlibc::infoLogger() << "mlibc warning: Failed to flush file"
<< frg::endlog;
}
return 0;
}
auto file = static_cast<mlibc::abstract_file *>(file_base);
frg::unique_lock lock(file->_lock);
if (file->flush())
return EOF;
return 0;
}
int setvbuf(FILE *file_base, char *, int mode, size_t) {
// TODO: We could also honor the buffer, but for now use just set the mode.
auto file = static_cast<mlibc::abstract_file *>(file_base);
if(mode == _IONBF) {
if(int e = file->update_bufmode(mlibc::buffer_mode::no_buffer); e) {
errno = e;
return -1;
}
}else if(mode == _IOLBF) {
if(int e = file->update_bufmode(mlibc::buffer_mode::line_buffer); e) {
errno = e;
return -1;
}
}else if(mode == _IOFBF) {
if(int e = file->update_bufmode(mlibc::buffer_mode::full_buffer); e) {
errno = e;
return -1;
}
}else{
errno = EINVAL;
return -1;
}
return 0;
}
void rewind(FILE *file_base) {
auto file = static_cast<mlibc::abstract_file *>(file_base);
frg::unique_lock lock(file->_lock);
file->seek(0, SEEK_SET);
file_base->__status_bits &= ~(__MLIBC_EOF_BIT | __MLIBC_ERROR_BIT);
}
int ungetc(int c, FILE *file_base) {
if (c == EOF)
return EOF;
auto file = static_cast<mlibc::abstract_file *>(file_base);
frg::unique_lock lock(file->_lock);
return file->unget(c);
}
#if __MLIBC_GLIBC_OPTION
void __fpurge(FILE *file_base) {
auto file = static_cast<mlibc::abstract_file *>(file_base);
frg::unique_lock lock(file->_lock);
file->purge();
}
#endif
@@ -0,0 +1,100 @@
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
#include <bits/ensure.h>
#include <mlibc/debug.hpp>
static const char *__mlibc_digits = "0123456789abcdefghijklmnopqrstuvwxyz";
intmax_t imaxabs(intmax_t num) {
return num < 0 ? -num : num;
}
imaxdiv_t imaxdiv(intmax_t number, intmax_t denom) {
imaxdiv_t r;
r.quot = number / denom;
r.rem = number % denom;
return r;
}
template <class T> T strtoxmax(const char *it, char **out, int base) {
T v = 0;
bool negate = false;
const unsigned char *s = (const unsigned char *)it;
int c;
if(std::is_signed_v<T>) {
if(*s == '+') {
s++;
}else if(*s == '-') {
negate = true;
s++;
}
}
do {
c = *s++;
} while (isspace(c));
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
if(base == 8) {
if(*it != 0)
goto parse_digits;
it++;
}else if(base == 16) {
if(*it != 0)
goto parse_digits;
it++;
if(*it != 'x' && *it != 'X')
goto parse_digits;
it++;
}
parse_digits:
while(*it) {
if(isspace(*it)) {
it++;
continue;
}
__ensure(base <= 10); // TODO: For base > 10 we need to implement tolower().
//auto c = strchr(__mlibc_digits, tolower(*it));
auto c = strchr(__mlibc_digits, *it);
if(!c || (c - __mlibc_digits) >= base)
break;
v = v * base + (c - __mlibc_digits);
it++;
}
if(std::is_signed_v<T>) {
if(negate)
v = -v;
}
if(out)
*out = const_cast<char *>(it);
return v;
}
intmax_t strtoimax(const char *it, char **out, int base) {
// TODO: This function has to check for overflow!
return strtoxmax<intmax_t>(it, out, base);
}
uintmax_t strtoumax(const char *it, char **out, int base) {
return strtoxmax<uintmax_t>(it, out, base);
}
intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
@@ -0,0 +1,196 @@
#include <limits.h>
#include <locale.h>
#include <string.h>
#include <bits/ensure.h>
#include <mlibc/debug.hpp>
#include <frg/optional.hpp>
namespace {
// Values of the C locale are defined by the C standard.
constexpr lconv c_lconv = {
const_cast<char *>("."), // decimal_point
const_cast<char *>(""), // thousands_sep
const_cast<char *>(""), // grouping
const_cast<char *>(""), // mon_decimal_point
const_cast<char *>(""), // mon_thousands_sep
const_cast<char *>(""), // mon_grouping
const_cast<char *>(""), // positive_sign
const_cast<char *>(""), // negative_sign
const_cast<char *>(""), // currency_symbol
CHAR_MAX, // frac_digits
CHAR_MAX, // p_cs_precedes
CHAR_MAX, // n_cs_precedes
CHAR_MAX, // p_sep_by_space
CHAR_MAX, // n_sep_by_space
CHAR_MAX, // p_sign_posn
CHAR_MAX, // n_sign_posn
const_cast<char *>(""), // int_curr_symbol
CHAR_MAX, // int_frac_digits
CHAR_MAX, // int_p_cs_precedes
CHAR_MAX, // int_n_cs_precedes
CHAR_MAX, // int_p_sep_by_space
CHAR_MAX, // int_n_sep_by_space
CHAR_MAX, // int_p_sign_posn
CHAR_MAX // int_n_sign_posn
};
} // namespace
namespace mlibc {
struct locale_description {
// Identifier of this locale. used in setlocale().
const char *name;
lconv lc;
};
constinit const locale_description c_locale{
.name = "C",
.lc = c_lconv
};
constinit const locale_description posix_locale{
.name = "POSIX",
.lc = c_lconv
};
const locale_description *query_locale_description(const char *name) {
if(!strcmp(name, "C"))
return &c_locale;
if(!strcmp(name, "POSIX"))
return &posix_locale;
return nullptr;
}
const locale_description *collate_facet;
const locale_description *ctype_facet;
const locale_description *monetary_facet;
const locale_description *numeric_facet;
const locale_description *time_facet;
const locale_description *messages_facet;
} // namespace mlibc
[[gnu::constructor]]
static void init_locale() {
mlibc::collate_facet = &mlibc::c_locale;
mlibc::ctype_facet = &mlibc::c_locale;
mlibc::monetary_facet = &mlibc::c_locale;
mlibc::numeric_facet = &mlibc::c_locale;
mlibc::time_facet = &mlibc::c_locale;
mlibc::messages_facet = &mlibc::c_locale;
}
char *setlocale(int category, const char *name) {
if(category == LC_ALL) {
// ´TODO: Implement correct return value when categories differ.
auto current_desc = mlibc::collate_facet;
__ensure(current_desc == mlibc::ctype_facet);
__ensure(current_desc == mlibc::monetary_facet);
__ensure(current_desc == mlibc::numeric_facet);
__ensure(current_desc == mlibc::time_facet);
__ensure(current_desc == mlibc::messages_facet);
if(name) {
// Our default C locale is the C locale.
if(!strlen(name))
name = "C";
auto new_desc = mlibc::query_locale_description(name);
if(!new_desc) {
mlibc::infoLogger() << "mlibc: Locale " << name
<< " is not supported" << frg::endlog;
return nullptr;
}
mlibc::collate_facet = new_desc;
mlibc::ctype_facet = new_desc;
mlibc::monetary_facet = new_desc;
mlibc::numeric_facet = new_desc;
mlibc::time_facet = new_desc;
mlibc::messages_facet = new_desc;
}
return const_cast<char *>(current_desc->name);
}else{
const mlibc::locale_description **facet_ptr;
switch(category) {
case LC_COLLATE:
facet_ptr = &mlibc::collate_facet;
break;
case LC_CTYPE:
facet_ptr = &mlibc::ctype_facet;
break;
case LC_MONETARY:
facet_ptr = &mlibc::monetary_facet;
break;
case LC_NUMERIC:
facet_ptr = &mlibc::numeric_facet;
break;
case LC_TIME:
facet_ptr = &mlibc::time_facet;
break;
case LC_MESSAGES:
facet_ptr = &mlibc::messages_facet;
break;
default:
mlibc::infoLogger() << "mlibc: Unexpected value " << category
<< " for category in setlocale()" << frg::endlog;
return nullptr;
}
auto current_desc = *facet_ptr;
if(name) {
// Our default C locale is the C locale.
if(!strlen(name))
name = "C";
auto new_desc = mlibc::query_locale_description(name);
if(!new_desc) {
mlibc::infoLogger() << "mlibc: Locale " << name
<< " is not supported" << frg::endlog;
return nullptr;
}
*facet_ptr = new_desc;
}
return const_cast<char *>(current_desc->name);
}
}
namespace {
lconv effective_lc;
} // namespace
struct lconv *localeconv(void) {
// Numeric locale.
const auto &numeric_lc = mlibc::numeric_facet->lc;
effective_lc.decimal_point = numeric_lc.decimal_point;
effective_lc.thousands_sep = numeric_lc.thousands_sep;
effective_lc.grouping = numeric_lc.grouping;
// Monetary locale.
const auto &monetary_lc = mlibc::monetary_facet->lc;
effective_lc.mon_decimal_point = monetary_lc.mon_decimal_point;
effective_lc.mon_thousands_sep = monetary_lc.mon_thousands_sep;
effective_lc.mon_grouping = monetary_lc.mon_grouping;
effective_lc.positive_sign = monetary_lc.positive_sign;
effective_lc.negative_sign = monetary_lc.negative_sign;
effective_lc.currency_symbol = monetary_lc.currency_symbol;
effective_lc.frac_digits = monetary_lc.frac_digits;
effective_lc.p_cs_precedes = monetary_lc.p_cs_precedes;
effective_lc.n_cs_precedes = monetary_lc.n_cs_precedes;
effective_lc.p_sep_by_space = monetary_lc.p_sep_by_space;
effective_lc.n_sep_by_space = monetary_lc.n_sep_by_space;
effective_lc.p_sign_posn = monetary_lc.p_sign_posn;
effective_lc.n_sign_posn = monetary_lc.n_sign_posn;
effective_lc.int_curr_symbol = monetary_lc.int_curr_symbol;
effective_lc.int_frac_digits = monetary_lc.int_frac_digits;
effective_lc.int_p_cs_precedes = monetary_lc.int_p_cs_precedes;
effective_lc.int_n_cs_precedes = monetary_lc.int_n_cs_precedes;
effective_lc.int_p_sep_by_space = monetary_lc.int_p_sep_by_space;
effective_lc.int_n_sep_by_space = monetary_lc.int_n_sep_by_space;
effective_lc.int_p_sign_posn = monetary_lc.int_p_sign_posn;
effective_lc.int_n_sign_posn = monetary_lc.int_n_sign_posn;
return &effective_lc;
}
@@ -0,0 +1,44 @@
#include <bits/ensure.h>
#include <errno.h>
#include <signal.h>
#include <mlibc/debug.hpp>
#include <mlibc/ansi-sysdeps.hpp>
__sighandler signal(int sn, __sighandler handler) {
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
struct sigaction old;
MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigaction, SIG_ERR);
if(int e = mlibc::sys_sigaction(sn, &sa, &old)){
errno = e;
return SIG_ERR;
}
return old.sa_handler;
}
int raise(int sig) {
MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getpid && mlibc::sys_kill, -1);
pid_t pid = mlibc::sys_getpid();
if (int e = mlibc::sys_kill(pid, sig)) {
errno = e;
return -1;
}
return 0;
}
// This is a POSIX extension, but we have it in here for sigsetjmp
int sigprocmask(int how, const sigset_t *__restrict set, sigset_t *__restrict retrieve) {
MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigprocmask, -1);
if(int e = mlibc::sys_sigprocmask(how, set, retrieve); e) {
errno = e;
return -1;
}
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,519 @@
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <stdio.h>
#include <wchar.h>
#include <setjmp.h>
#include <limits.h>
#include <frg/random.hpp>
#include <mlibc/debug.hpp>
#include <bits/ensure.h>
#include <bits/sigset_t.h>
#include <mlibc/allocator.hpp>
#include <mlibc/charcode.hpp>
#include <mlibc/ansi-sysdeps.hpp>
#include <mlibc/strtofp.hpp>
#include <mlibc/strtol.hpp>
#include <mlibc/threads.hpp>
#include <mlibc/global-config.hpp>
#if __MLIBC_POSIX_OPTION
#include <pthread.h>
#endif // __MLIBC_POSIX_OPTION
extern "C" int __cxa_atexit(void (*function)(void *), void *argument, void *dso_tag);
void __mlibc_do_finalize();
namespace {
// According to the first paragraph of [C11 7.22.7],
// mblen(), mbtowc() and wctomb() have an internal state.
// The string functions mbstowcs() and wcstombs() do *not* have this state.
thread_local __mlibc_mbstate mblen_state = __MLIBC_MBSTATE_INITIALIZER;
thread_local __mlibc_mbstate mbtowc_state = __MLIBC_MBSTATE_INITIALIZER;
__mlibc_mutex exit_mutex = __MLIBC_THREAD_MUTEX_INITIALIZER;
} // namespace
double atof(const char *string) {
return strtod(string, nullptr);
}
int atoi(const char *string) {
return strtol(string, nullptr, 10);
}
long atol(const char *string) {
return strtol(string, nullptr, 10);
}
long long atoll(const char *string) {
return strtoll(string, nullptr, 10);
}
// POSIX extensions but are here for simplicities sake. Forward declaration is here
// to avoid exporting sigprocmask when posix is disabled.
int sigprocmask(int, const sigset_t *__restrict, sigset_t *__restrict);
extern "C" {
__attribute__((__returns_twice__)) int __sigsetjmp(sigjmp_buf buffer, int savesigs) {
buffer[0].__savesigs = savesigs;
if (savesigs)
sigprocmask(0, nullptr, &buffer[0].__sigset);
return 0;
}
}
__attribute__((__noreturn__)) void siglongjmp(sigjmp_buf buffer, int value) {
if (buffer[0].__savesigs)
sigprocmask(SIG_SETMASK, &buffer[0].__sigset, nullptr);
jmp_buf b;
b[0].__reg_state = buffer[0].__reg_state;
longjmp(b, value);
}
double strtod(const char *__restrict string, char **__restrict end) {
return mlibc::strtofp<double>(string, end);
}
float strtof(const char *__restrict string, char **__restrict end) {
return mlibc::strtofp<float>(string, end);
}
long double strtold(const char *__restrict string, char **__restrict end) {
return mlibc::strtofp<long double>(string, end);
}
long strtol(const char *__restrict string, char **__restrict end, int base) {
return mlibc::stringToInteger<long, char>(string, end, base);
}
long long strtoll(const char *__restrict string, char **__restrict end, int base) {
return mlibc::stringToInteger<long long, char>(string, end, base);
}
unsigned long strtoul(const char *__restrict string, char **__restrict end, int base) {
return mlibc::stringToInteger<unsigned long, char>(string, end, base);
}
unsigned long long strtoull(const char *__restrict string, char **__restrict end, int base) {
return mlibc::stringToInteger<unsigned long long, char>(string, end, base);
}
frg::mt19937 __mlibc_rand_engine;
int rand() {
// rand() is specified to return a positive number so we discard the MSB.
return static_cast<int>(__mlibc_rand_engine() & 0x7FFFFFFF);
}
static unsigned temper(unsigned x) {
x ^= x >> 11;
x ^= x << 7 & 0x9D2C5680;
x ^= x << 15 & 0xEFC60000;
x ^= x >> 18;
return x;
}
int rand_r(unsigned *seed) {
return temper(*seed = *seed * 1103515245 + 12345) / 2;
}
void srand(unsigned int s) {
__mlibc_rand_engine.seed(s);
}
void *aligned_alloc(size_t alignment, size_t size) {
void *ptr;
// alignment must be a power of two, and size % alignment must be 0
if (alignment & (alignment - 1) || size & (alignment - 1)) {
errno = EINVAL;
return nullptr;
}
// posix_memalign requires that the alignment is a multiple of sizeof(void *)
if (alignment < sizeof(void *))
alignment = sizeof(void *);
int ret = posix_memalign(&ptr, alignment, size);
if (ret) {
errno = ret;
return nullptr;
}
return ptr;
}
void *calloc(size_t count, size_t size) {
// we want to ensure that count*size > SIZE_MAX doesn't happen
// to prevent overflowing, we divide both sides of the inequality by size and check with that
if(size && count > (SIZE_MAX / size)) {
errno = EINVAL;
return nullptr;
}
// TODO: this could be done more efficient if the OS gives us already zero'd pages
void *ptr = malloc(count * size);
if(!ptr)
return nullptr;
memset(ptr, 0, count * size);
return ptr;
}
// free() is provided by the platform
// malloc() is provided by the platform
// realloc() is provided by the platform
void abort(void) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGABRT);
if (mlibc::sys_sigprocmask) {
mlibc::sys_sigprocmask(SIG_UNBLOCK, &set, nullptr);
}
raise(SIGABRT);
sigfillset(&set);
sigdelset(&set, SIGABRT);
if (mlibc::sys_sigprocmask) {
mlibc::sys_sigprocmask(SIG_SETMASK, &set, nullptr);
}
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (mlibc::sys_sigaction(SIGABRT, &sa, nullptr))
mlibc::panicLogger() << "mlibc: sigaction failed in abort" << frg::endlog;
if (raise(SIGABRT))
mlibc::panicLogger() << "mlibc: raise failed in abort" << frg::endlog;
__builtin_trap();
}
int atexit(void (*func)(void)) {
// TODO: the function pointer types are not compatible;
// the conversion here is undefined behavior. its fine to do
// this on the x86_64 abi though.
__cxa_atexit((void (*) (void *))func, nullptr, nullptr);
return 0;
}
int at_quick_exit(void (*func)(void)) {
(void)func;
__ensure(!"Not implemented");
__builtin_unreachable();
}
void exit(int status) {
// for concurrent calls to exit() or quick_exit(), all but the first shall block until termination
// see https://austingroupbugs.net/view.php?id=1845
mlibc::thread_mutex_lock(&exit_mutex);
__mlibc_do_finalize();
mlibc::sys_exit(status);
}
void _Exit(int status) {
mlibc::sys_exit(status);
}
// getenv() is provided by POSIX
void quick_exit(int) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
extern char **environ;
int system(const char *command) {
int status = -1;
pid_t child;
MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fork && mlibc::sys_waitpid &&
mlibc::sys_execve && mlibc::sys_sigprocmask && mlibc::sys_sigaction, -1);
#if __MLIBC_POSIX_OPTION
pthread_testcancel();
#endif // __MLIBC_POSIX_OPTION
if (!command) {
return 1;
}
struct sigaction new_sa, old_int, old_quit;
sigset_t new_mask, old_mask;
new_sa.sa_handler = SIG_IGN;
new_sa.sa_flags = 0;
sigemptyset(&new_sa.sa_mask);
mlibc::sys_sigaction(SIGINT, &new_sa, &old_int);
mlibc::sys_sigaction(SIGQUIT, &new_sa, &old_quit);
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGCHLD);
mlibc::sys_sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
if (int e = mlibc::sys_fork(&child)) {
errno = e;
} else if (!child) {
mlibc::sys_sigaction(SIGINT, &old_int, nullptr);
mlibc::sys_sigaction(SIGQUIT, &old_quit, nullptr);
mlibc::sys_sigprocmask(SIG_SETMASK, &old_mask, nullptr);
const char *args[] = {
"sh", "-c", command, nullptr
};
mlibc::sys_execve("/bin/sh", const_cast<char **>(args), environ);
_Exit(127);
} else {
int err;
pid_t unused;
while ((err = mlibc::sys_waitpid(child, &status, 0, nullptr, &unused)) < 0) {
if (err == EINTR)
continue;
errno = err;
status = -1;
}
}
mlibc::sys_sigaction(SIGINT, &old_int, nullptr);
mlibc::sys_sigaction(SIGQUIT, &old_quit, nullptr);
mlibc::sys_sigprocmask(SIG_SETMASK, &old_mask, nullptr);
return status;
}
char *mktemp(char *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
void *bsearch(const void *key, const void *base, size_t count, size_t size,
int (*compare)(const void *, const void *)) {
// Invariant: Element is in the interval [i, j).
size_t i = 0;
size_t j = count;
while(i < j) {
size_t k = (j - i) / 2;
auto element = reinterpret_cast<const char *>(base) + (i + k) * size;
auto res = compare(key, element);
if(res < 0) {
j = i + k;
}else if(res > 0) {
i = i + k + 1;
}else{
return const_cast<char *>(element);
}
}
__ensure(i == j);
return nullptr;
}
static int qsort_callback(const void *a, const void *b, void *arg) {
auto compare = reinterpret_cast<int (*)(const void *, const void *)>(arg);
return compare(a, b);
}
void qsort(void *base, size_t count, size_t size,
int (*compare)(const void *, const void *)) {
return qsort_r(base, count, size, qsort_callback, (void *) compare);
}
void qsort_r(void *base, size_t count, size_t size,
int (*compare)(const void *, const void *, void *),
void *arg) {
// TODO: implement a faster sort
for(size_t i = 0; i < count; i++) {
void *u = (void *)((uintptr_t)base + i * size);
for(size_t j = i + 1; j < count; j++) {
void *v = (void *)((uintptr_t)base + j * size);
if(compare(u, v, arg) <= 0)
continue;
// swap u and v
char *u_bytes = (char *)u;
char *v_bytes = (char *)v;
for(size_t k = 0; k < size; k++) {
char temp = u_bytes[k];
u_bytes[k] = v_bytes[k];
v_bytes[k] = temp;
}
}
}
}
int abs(int num) {
return num < 0 ? -num : num;
}
long labs(long num) {
return num < 0 ? -num : num;
}
long long llabs(long long num) {
return num < 0 ? -num : num;
}
div_t div(int number, int denom) {
div_t r;
r.quot = number / denom;
r.rem = number % denom;
return r;
}
ldiv_t ldiv(long number, long denom) {
ldiv_t r;
r.quot = number / denom;
r.rem = number % denom;
return r;
}
lldiv_t lldiv(long long number, long long denom) {
lldiv_t r;
r.quot = number / denom;
r.rem = number % denom;
return r;
}
int mblen(const char *mbs, size_t mb_limit) {
auto cc = mlibc::current_charcode();
wchar_t wc;
mlibc::code_seq<const char> nseq{mbs, mbs + mb_limit};
mlibc::code_seq<wchar_t> wseq{&wc, &wc + 1};
if(!mbs) {
mblen_state = __MLIBC_MBSTATE_INITIALIZER;
return cc->has_shift_states;
}
if(auto e = cc->decode_wtranscode(nseq, wseq, mblen_state); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return nseq.it - mbs;
}
int mbtowc(wchar_t *__restrict wc, const char *__restrict mb, size_t max_size) {
auto cc = mlibc::current_charcode();
__ensure(max_size);
// If wc is NULL, decode into a single local character which we discard
// to obtain the length.
wchar_t tmp_wc;
if (!wc)
wc = &tmp_wc;
if (mb) {
if (*mb) {
mlibc::code_seq<wchar_t> wseq{wc, wc + 1};
mlibc::code_seq<const char> nseq{mb, mb + frg::min(max_size, MB_CUR_MAX)};
auto e = cc->decode_wtranscode(nseq, wseq, mbtowc_state);
switch(e) {
// We keep the state, so we can simply return here.
case mlibc::charcode_error::input_underflow:
case mlibc::charcode_error::null: {
return nseq.it - mb;
}
case mlibc::charcode_error::illegal_input: {
errno = -EILSEQ;
return -1;
}
case mlibc::charcode_error::dirty: {
mlibc::panicLogger() << "decode_wtranscode() charcode_error::dirty errors are not handled" << frg::endlog;
break;
}
case mlibc::charcode_error::output_overflow: {
mlibc::panicLogger() << "decode_wtranscode() charcode_error::output_overflow errors are not handled" << frg::endlog;
break;
}
}
__builtin_unreachable();
} else {
*wc = L'\0';
return 0; // When mbs is a null byte, return 0
}
} else {
mblen_state = __MLIBC_MBSTATE_INITIALIZER;
return cc->has_shift_states;
}
}
int wctomb(char *, wchar_t) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
size_t mbstowcs(wchar_t *__restrict wcs, const char *__restrict mbs, size_t wc_limit) {
auto cc = mlibc::current_charcode();
__mlibc_mbstate st = __MLIBC_MBSTATE_INITIALIZER;
mlibc::code_seq<const char> nseq{mbs, nullptr};
mlibc::code_seq<wchar_t> wseq{wcs, wcs + wc_limit};
if(!wcs) {
size_t size;
if(auto e = cc->decode_wtranscode_length(nseq, &size, st); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return size;
}
if(auto e = cc->decode_wtranscode(nseq, wseq, st); e != mlibc::charcode_error::null) {
__ensure(!"decode_wtranscode() errors are not handled");
__builtin_unreachable();
}else{
size_t n = wseq.it - wcs;
if(n < wc_limit) // Null-terminate resulting wide string.
wcs[n] = 0;
return n;
}
}
size_t wcstombs(char *__restrict mb_string, const wchar_t *__restrict wc_string, size_t max_size) {
const wchar_t *wcs = wc_string;
return wcsrtombs(mb_string, &wcs, max_size, nullptr);
}
void free(void *ptr) {
// TODO: Print PID only if POSIX option is enabled.
if (mlibc::globalConfig().debugMalloc) {
mlibc::infoLogger() << "mlibc (PID ?): free() on "
<< ptr << frg::endlog;
if((uintptr_t)ptr & 1)
mlibc::infoLogger() << __builtin_return_address(0) << frg::endlog;
}
getAllocator().free(ptr);
}
void *malloc(size_t size) {
auto nptr = getAllocator().allocate(size);
// TODO: Print PID only if POSIX option is enabled.
if (mlibc::globalConfig().debugMalloc)
mlibc::infoLogger() << "mlibc (PID ?): malloc() returns "
<< nptr << frg::endlog;
return nptr;
}
void *realloc(void *ptr, size_t size) {
auto nptr = getAllocator().reallocate(ptr, size);
// TODO: Print PID only if POSIX option is enabled.
if (mlibc::globalConfig().debugMalloc)
mlibc::infoLogger() << "mlibc (PID ?): realloc() on "
<< ptr << " returns " << nptr << frg::endlog;
return nptr;
}
int posix_memalign(void **out, size_t align, size_t size) {
if(align < sizeof(void *))
return EINVAL;
if(align & (align - 1)) // Make sure that align is a power of two.
return EINVAL;
auto p = getAllocator().allocate(frg::max(align, size));
if(!p)
return ENOMEM;
// Hope that the alignment was respected. This works on the current allocator.
// TODO: Make the allocator alignment-aware.
__ensure(!(reinterpret_cast<uintptr_t>(p) & (align - 1)));
*out = p;
return 0;
}
@@ -0,0 +1,550 @@
#undef _GNU_SOURCE
#include <string.h>
#include <errno.h>
#include <wchar.h>
#include <ctype.h>
#include <bits/ensure.h>
#include <mlibc/strtol.hpp>
// memset() is defined in options/internals.
// memcpy() is defined in options/internals.
// memmove() is defined in options/internals.
// strlen() is defined in options/internals.
char *strcpy(char *__restrict dest, const char *src) {
char *dest_bytes = (char *)dest;
char *src_bytes = (char *)src;
while(*src_bytes)
*(dest_bytes++) = *(src_bytes++);
*dest_bytes = 0;
return dest;
}
char *strncpy(char *__restrict dest, const char *src, size_t max_size) {
auto dest_bytes = static_cast<char *>(dest);
auto src_bytes = static_cast<const char *>(src);
size_t i = 0;
while(*src_bytes && i < max_size) {
*(dest_bytes++) = *(src_bytes++);
i++;
}
while(i < max_size) {
*(dest_bytes++) = 0;
i++;
}
return dest;
}
char *strcat(char *__restrict dest, const char *__restrict src) {
strcpy(dest + strlen(dest), src);
return dest;
}
char *strncat(char *__restrict dest, const char *__restrict src, size_t max_size) {
auto dest_bytes = static_cast<char *>(dest);
auto src_bytes = static_cast<const char *>(src);
dest_bytes += strlen(dest);
size_t i = 0;
while(*src_bytes && i < max_size) {
*(dest_bytes++) = *(src_bytes++);
i++;
}
*dest_bytes = 0;
return dest;
}
int memcmp(const void *a, const void *b, size_t size) {
for(size_t i = 0; i < size; i++) {
auto a_byte = static_cast<const unsigned char *>(a)[i];
auto b_byte = static_cast<const unsigned char *>(b)[i];
if(a_byte < b_byte)
return -1;
if(a_byte > b_byte)
return 1;
}
return 0;
}
int strcmp(const char *a, const char *b) {
size_t i = 0;
while(true) {
unsigned char a_byte = a[i];
unsigned char b_byte = b[i];
if(!a_byte && !b_byte)
return 0;
// If only one char is null, one of the following cases applies.
if(a_byte < b_byte)
return -1;
if(a_byte > b_byte)
return 1;
i++;
}
}
int strcoll(const char *a, const char *b) {
// TODO: strcoll should take "LC_COLLATE" into account.
return strcmp(a, b);
}
int strncmp(const char *a, const char *b, size_t max_size) {
size_t i = 0;
while(true) {
if(!(i < max_size))
return 0;
unsigned char a_byte = a[i];
unsigned char b_byte = b[i];
if(!a_byte && !b_byte)
return 0;
// If only one char is null, one of the following cases applies.
if(a_byte < b_byte)
return -1;
if(a_byte > b_byte)
return 1;
i++;
}
}
size_t strxfrm(char *__restrict dest, const char *__restrict src, size_t n) {
// NOTE: This might not work for non ANSI charsets.
size_t l = strlen(src);
// man page: If the value returned is n or more, the contents of dest are indeterminate.
if(n > l)
strncpy(dest, src, n);
return l;
}
void *memchr(const void *s, int c, size_t size) {
auto s_bytes = static_cast<const unsigned char *>(s);
for(size_t i = 0; i < size; i++)
if(s_bytes[i] == static_cast<unsigned char>(c))
return const_cast<unsigned char *>(s_bytes + i);
return nullptr;
}
char *strchr(const char *s, int c) {
size_t i = 0;
while(s[i]) {
if(s[i] == c)
return const_cast<char *>(&s[i]);
i++;
}
if(c == 0)
return const_cast<char *>(&s[i]);
return nullptr;
}
size_t strcspn(const char *s, const char *chrs) {
size_t n = 0;
while(true) {
if(!s[n] || strchr(chrs, s[n]))
return n;
n++;
}
}
char *strpbrk(const char *s, const char *chrs) {
size_t n = 0;
while(s[n]) {
if(strchr(chrs, s[n]))
return const_cast<char *>(s + n);
n++;
}
return nullptr;
}
char *strrchr(const char *s, int c) {
// The null-terminator is considered to be part of the string.
size_t length = strlen(s);
for(size_t i = 0; i <= length; i++) {
if(s[length - i] == c)
return const_cast<char *>(s + (length - i));
}
return nullptr;
}
size_t strspn(const char *s, const char *chrs) {
size_t n = 0;
while(true) {
if(!s[n] || !strchr(chrs, s[n]))
return n;
n++;
}
}
char *strstr(const char *s, const char *pattern) {
for(size_t i = 0; s[i]; i++) {
bool found = true;
for(size_t j = 0; pattern[j]; j++) {
if(!pattern[j] || s[i + j] == pattern[j])
continue;
found = false;
break;
}
if(found)
return const_cast<char *>(&s[i]);
}
return nullptr;
}
char *strtok_r(char *__restrict s, const char *__restrict del, char **__restrict m) {
__ensure(m);
// We use *m = null to memorize that the entire string was consumed.
char *tok;
if(s) {
tok = s;
}else if(*m) {
tok = *m;
}else {
return nullptr;
}
// Skip initial delimiters.
// After this loop: *tok is non-null iff we return a token.
while(*tok && strchr(del, *tok))
tok++;
// Replace the following delimiter by a null-terminator.
// After this loop: *p is null iff we reached the end of the string.
auto p = tok;
while(*p && !strchr(del, *p))
p++;
if(*p) {
*p = 0;
*m = p + 1;
}else{
*m = nullptr;
}
if(p == tok)
return nullptr;
return tok;
}
char *strtok(char *__restrict s, const char *__restrict delimiter) {
static char *saved;
return strtok_r(s, delimiter, &saved);
}
// This is a GNU extension.
char *strchrnul(const char *s, int c) {
size_t i = 0;
while(s[i]) {
if(s[i] == c)
return const_cast<char *>(s + i);
i++;
}
return const_cast<char *>(s + i);
}
double wcstod(const wchar_t *__restrict, wchar_t **__restrict) { MLIBC_STUB_BODY; }
float wcstof(const wchar_t *__restrict, wchar_t **__restrict) { MLIBC_STUB_BODY; }
long double wcstold(const wchar_t *__restrict, wchar_t **__restrict) { MLIBC_STUB_BODY; }
long wcstol(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base) {
return mlibc::stringToInteger<long, wchar_t>(nptr, endptr, base);
}
unsigned long wcstoul(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base) {
return mlibc::stringToInteger<unsigned long, wchar_t>(nptr, endptr, base);
}
long long wcstoll(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base) {
return mlibc::stringToInteger<long long, wchar_t>(nptr, endptr, base);
}
unsigned long long wcstoull(const wchar_t *__restrict nptr, wchar_t **__restrict endptr, int base) {
return mlibc::stringToInteger<unsigned long long, wchar_t>(nptr, endptr, base);
}
wchar_t *wcscpy(wchar_t *__restrict dest, const wchar_t *__restrict src) {
wchar_t *a = dest;
while((*dest++ = *src++));
return a;
}
wchar_t *wcsncpy(wchar_t *__restrict dest, const wchar_t *__restrict src, size_t n) {
wchar_t *a = dest;
while(n && *src)
n--, *dest++ = *src++;
wmemset(dest, 0, n);
return a;
}
wchar_t *wmemcpy(wchar_t *__restrict dest, const wchar_t *__restrict src, size_t n) {
memcpy(dest, src, n * sizeof(wchar_t));
return dest;
}
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t n) {
memmove(dest, src, n * sizeof(wchar_t));
return dest;
}
wchar_t *wcscat(wchar_t *__restrict dest, const wchar_t *__restrict src) {
wcscpy(dest + wcslen(dest), src);
return dest;
}
wchar_t *wcsncat(wchar_t *__restrict, const wchar_t *__restrict, size_t) { MLIBC_STUB_BODY; }
int wcscmp(const wchar_t *l, const wchar_t *r) {
for(; *l == *r && *l && *r; l++, r++);
return *l - *r;
}
int wcscoll(const wchar_t *, const wchar_t *) { MLIBC_STUB_BODY; }
int wcsncmp(const wchar_t *, const wchar_t *, size_t) { MLIBC_STUB_BODY; }
int wcsxfrm(wchar_t *__restrict, const wchar_t *__restrict, size_t) { MLIBC_STUB_BODY; }
int wmemcmp(const wchar_t *a, const wchar_t *b, size_t size) {
for(size_t i = 0; i < size; i++) {
auto a_byte = a[i];
auto b_byte = b[i];
if(a_byte < b_byte)
return -1;
if(a_byte > b_byte)
return 1;
}
return 0;
}
wchar_t *wcschr(const wchar_t *s, wchar_t c) {
if(!c)
return (wchar_t *)s + wcslen(s);
for(; *s && *s != c; s++);
return *s ? (wchar_t *)s : nullptr;
}
size_t wcscspn(const wchar_t *, const wchar_t *) { MLIBC_STUB_BODY; }
wchar_t *wcspbrk(const wchar_t *, const wchar_t *) { MLIBC_STUB_BODY; }
wchar_t *wcsrchr(const wchar_t *s, wchar_t c) {
const wchar_t *p;
for(p = s + wcslen(s); p >= s && *p != c; p--);
return p >= s ? (wchar_t *)p : nullptr;
}
size_t wcsspn(const wchar_t *, const wchar_t *) { MLIBC_STUB_BODY; }
wchar_t *wcsstr(const wchar_t *, const wchar_t *) { MLIBC_STUB_BODY; }
wchar_t *wcstok(wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict) { MLIBC_STUB_BODY; }
wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t size) {
auto s_bytes = s;
for(size_t i = 0; i < size; i++)
if(s_bytes[i] == c)
return const_cast<wchar_t *>(s_bytes + i);
return nullptr;
}
size_t wcslen(const wchar_t *s) {
const wchar_t *a;
for(a = s; *s; s++);
return s-a;
}
wchar_t *wmemset(wchar_t *d, wchar_t c, size_t n) {
wchar_t *ret = d;
while(n--)
*d++ = c;
return ret;
}
char *strerror(int e) {
const char *s;
switch(e) {
case EAGAIN: s = "Operation would block (EAGAIN)"; break;
case EACCES: s = "Access denied (EACCESS)"; break;
case EBADF: s = "Bad file descriptor (EBADF)"; break;
case EEXIST: s = "File exists already (EEXIST)"; break;
case EFAULT: s = "Access violation (EFAULT)"; break;
case EINTR: s = "Operation interrupted (EINTR)"; break;
case EINVAL: s = "Invalid argument (EINVAL)"; break;
case EIO: s = "I/O error (EIO)"; break;
case EISDIR: s = "Resource is directory (EISDIR)"; break;
case ENOENT: s = "No such file or directory (ENOENT)"; break;
case ENOMEM: s = "Out of memory (ENOMEM)"; break;
case ENOTDIR: s = "Expected directory instead of file (ENOTDIR)"; break;
case ENOSYS: s = "Operation not implemented (ENOSYS)"; break;
case EPERM: s = "Operation not permitted (EPERM)"; break;
case EPIPE: s = "Broken pipe (EPIPE)"; break;
case ESPIPE: s = "Seek not possible (ESPIPE)"; break;
case ENXIO: s = "No such device or address (ENXIO)"; break;
case ENOEXEC: s = "Exec format error (ENOEXEC)"; break;
case ENOSPC: s = "No space left on device (ENOSPC)"; break;
case ENOTSOCK: s = "Socket operation on non-socket (ENOTSOCK)"; break;
case ENOTCONN: s = "Transport endpoint is not connected (ENOTCONN)"; break;
case EDOM: s = "Numerical argument out of domain (EDOM)"; break;
case EILSEQ: s = "Invalid or incomplete multibyte or wide character (EILSEQ)"; break;
case ERANGE: s = "Numerical result out of range (ERANGE)"; break;
case E2BIG: s = "Argument list too long (E2BIG)"; break;
case EADDRINUSE: s = "Address already in use (EADDRINUSE)"; break;
case EADDRNOTAVAIL: s = "Cannot assign requested address (EADDRNOTAVAIL)"; break;
case EAFNOSUPPORT: s = "Address family not supported by protocol (EAFNOSUPPORT)"; break;
case EALREADY: s = "Operation already in progress (EALREADY)"; break;
case EBADMSG: s = "Bad message (EBADMSG)"; break;
case EBUSY: s = "Device or resource busy (EBUSY)"; break;
case ECANCELED: s = "Operation canceled (ECANCELED)"; break;
case ECHILD: s = "No child processes (ECHILD)"; break;
case ECONNABORTED: s = "Software caused connection abort (ECONNABORTED)"; break;
case ECONNREFUSED: s = "Connection refused (ECONNREFUSED)"; break;
case ECONNRESET: s = "Connection reset by peer (ECONNRESET)"; break;
case EDEADLK: s = "Resource deadlock avoided (EDEADLK)"; break;
case EDESTADDRREQ: s = "Destination address required (EDESTADDRREQ)"; break;
case EDQUOT: s = "Disk quota exceeded (EDQUOT)"; break;
case EFBIG: s = "File too large (EFBIG)"; break;
case EHOSTUNREACH: s = "No route to host (EHOSTUNREACH)"; break;
case EIDRM: s = "Identifier removed (EIDRM)"; break;
case EINPROGRESS: s = "Operation now in progress (EINPROGRESS)"; break;
case EISCONN: s = "Transport endpoint is already connected (EISCONN)"; break;
case ELOOP: s = "Too many levels of symbolic links (ELOOP)"; break;
case EMFILE: s = "Too many open files (EMFILE)"; break;
case EMLINK: s = "Too many links (EMLINK)"; break;
case EMSGSIZE: s = "Message too long (EMSGSIZE)"; break;
case EMULTIHOP: s = "Multihop attempted (EMULTIHOP)"; break;
case ENAMETOOLONG: s = "File name too long (ENAMETOOLONG)"; break;
case ENETDOWN: s = "Network is down (ENETDOWN)"; break;
case ENETRESET: s = "Network dropped connection on reset (ENETRESET)"; break;
case ENETUNREACH: s = "Network is unreachable (ENETUNREACH)"; break;
case ENFILE: s = "Too many open files in system (ENFILE)"; break;
case ENOBUFS: s = "No buffer space available (ENOBUFS)"; break;
case ENODEV: s = "No such device (ENODEV)"; break;
case ENOLCK: s = "No locks available (ENOLCK)"; break;
case ENOLINK: s = "Link has been severed (ENOLINK)"; break;
case ENOMSG: s = "No message of desired type (ENOMSG)"; break;
case ENOPROTOOPT: s = "Protocol not available (ENOPROTOOPT)"; break;
case ENOTEMPTY: s = "Directory not empty (ENOTEMPTY)"; break;
case ENOTRECOVERABLE: s = "Sate not recoverable (ENOTRECOVERABLE)"; break;
case ENOTSUP: s = "Operation not supported (ENOTSUP)"; break;
case ENOTTY: s = "Inappropriate ioctl for device (ENOTTY)"; break;
case EOVERFLOW: s = "Value too large for defined datatype (EOVERFLOW)"; break;
#if EOPNOTSUPP != ENOTSUP
/* these are aliases on the mlibc abi */
case EOPNOTSUPP: s = "Operation not supported (EOPNOTSUP)"; break;
#endif
case EOWNERDEAD: s = "Owner died (EOWNERDEAD)"; break;
case EPROTO: s = "Protocol error (EPROTO)"; break;
case EPROTONOSUPPORT: s = "Protocol not supported (EPROTONOSUPPORT)"; break;
case EPROTOTYPE: s = "Protocol wrong type for socket (EPROTOTYPE)"; break;
case EROFS: s = "Read-only file system (EROFS)"; break;
case ESRCH: s = "No such process (ESRCH)"; break;
case ESTALE: s = "Stale file handle (ESTALE)"; break;
case ETIMEDOUT: s = "Connection timed out (ETIMEDOUT)"; break;
case ETXTBSY: s = "Text file busy (ETXTBSY)"; break;
case EXDEV: s = "Invalid cross-device link (EXDEV)"; break;
case ENODATA: s = "No data available (ENODATA)"; break;
case ETIME: s = "Timer expired (ETIME)"; break;
case ENOKEY: s = "Required key not available (ENOKEY)"; break;
case ESHUTDOWN: s = "Cannot send after transport endpoint shutdown (ESHUTDOWN)"; break;
case EHOSTDOWN: s = "Host is down (EHOSTDOWN)"; break;
case EBADFD: s = "File descriptor in bad state (EBADFD)"; break;
case ENOMEDIUM: s = "No medium found (ENOMEDIUM)"; break;
case ENOTBLK: s = "Block device required (ENOTBLK)"; break;
case ENONET: s = "Machine is not on the network (ENONET)"; break;
case EPFNOSUPPORT: s = "Protocol family not supported (EPFNOSUPPORT)"; break;
case ESOCKTNOSUPPORT: s = "Socket type not supported (ESOCKTNOSUPPORT)"; break;
case ESTRPIPE: s = "Streams pipe error (ESTRPIPE)"; break;
case EREMOTEIO: s = "Remote I/O error (EREMOTEIO)"; break;
case ERFKILL: s = "Operation not possible due to RF-kill (ERFKILL)"; break;
case EBADR: s = "Invalid request descriptor (EBADR)"; break;
case EUNATCH: s = "Protocol driver not attached (EUNATCH)"; break;
case EMEDIUMTYPE: s = "Wrong medium type (EMEDIUMTYPE)"; break;
case EREMOTE: s = "Object is remote (EREMOTE)"; break;
case EKEYREJECTED: s = "Key was rejected by service (EKEYREJECTED)"; break;
case EUCLEAN: s = "Structure needs cleaning (EUCLEAN)"; break;
case EBADSLT: s = "Invalid slot (EBADSLT)"; break;
case ENOANO: s = "No anode (ENOANO)"; break;
case ENOCSI: s = "No CSI structure available (ENOCSI)"; break;
case ENOSTR: s = "Device not a stream (ENOSTR)"; break;
case ETOOMANYREFS: s = "Too many references: cannot splice (ETOOMANYREFS)"; break;
case ENOPKG: s = "Package not installed (ENOPKG)"; break;
case EKEYREVOKED: s = "Key has been revoked (EKEYREVOKED)"; break;
case EXFULL: s = "Exchange full (EXFULL)"; break;
case ELNRNG: s = "Link number out of range (ELNRNG)"; break;
case ENOTUNIQ: s = "Name not unique on network (ENOTUNIQ)"; break;
case ERESTART: s = "Interrupted system call should be restarted (ERESTART)"; break;
case EUSERS: s = "Too many users (EUSERS)"; break;
#ifdef EIEIO
case EIEIO: s = "Computer bought the farm; OS internal error (EIEIO)"; break;
#endif
default:
s = "Unknown error code (?)";
}
return const_cast<char *>(s);
}
// strlen() is defined in options/internals.
extern "C" char *__gnu_strerror_r(int e, char *buffer, size_t bufsz) {
auto s = strerror(e);
strncpy(buffer, s, bufsz);
return buffer;
}
// POSIX extensions.
int strerror_r(int e, char *buffer, size_t bufsz) {
auto s = strerror(e);
strncpy(buffer, s, bufsz);
// Note that strerror_r does not set errno on error!
if(strlen(s) >= bufsz)
return ERANGE;
return 0;
}
void *mempcpy(void *dest, const void *src, size_t len) {
return (char *)memcpy(dest, src, len) + len;
}
// GNU extensions.
// Taken from musl.
int strverscmp(const char *l0, const char *r0) {
const unsigned char *l = (const unsigned char *)l0;
const unsigned char *r = (const unsigned char *)r0;
size_t i, dp, j;
int z = 1;
/* Find maximal matching prefix and track its maximal digit
* suffix and whether those digits are all zeros. */
for(dp = i = 0; l[i] == r[i]; i++) {
int c = l[i];
if(!c)
return 0;
if(!isdigit(c))
dp = i + 1, z = 1;
else if(c != '0')
z = 0;
}
if(l[dp] != '0' && r[dp] != '0') {
/* If we're not looking at a digit sequence that began
* with a zero, longest digit string is greater. */
for(j = i; isdigit(l[j]); j++) {
if(!isdigit(r[j]))
return 1;
}
if(isdigit(r[j]))
return -1;
} else if(z && dp < i && (isdigit(l[i]) || isdigit(r[i]))) {
/* Otherwise, if common prefix of digit sequence is
* all zeros, digits order less than non-digits. */
return (unsigned char)(l[i] - '0') - (unsigned char)(r[i] - '0');
}
return l[i] - r[i];
}
void *memmem(const void *hs, size_t haystackLen, const void *nd, size_t needleLen) {
const char *haystack = static_cast<const char *>(hs);
const char *needle = static_cast<const char *>(nd);
for (size_t i = 0; i < haystackLen; i++) {
bool found = true;
for (size_t j = 0; j < needleLen; j++) {
if (i + j >= haystackLen || haystack[i + j] != needle[j]) {
found = false;
break;
}
}
if(found)
return const_cast<char *>(&haystack[i]);
}
return nullptr;
}
@@ -0,0 +1,97 @@
#include <abi-bits/errno.h>
#include <bits/ensure.h>
#include <mlibc/debug.hpp>
#include <mlibc/thread.hpp>
#include <mlibc/threads.hpp>
#include <threads.h>
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
int res = mlibc::thread_create(thr, nullptr, reinterpret_cast<void *>(func), arg, true);
if(!res) {
return thrd_success;
}
return (res == ENOMEM) ? thrd_nomem : thrd_error;
}
int thrd_equal(thrd_t t1, thrd_t t2) {
if(t1 == t2) {
return 1;
}
return 0;
}
thrd_t thrd_current(void) {
return reinterpret_cast<thrd_t>(mlibc::get_current_tcb());
}
int thrd_sleep(const struct timespec *, struct timespec *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
void thrd_yield(void) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
int thrd_detach(thrd_t) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
int thrd_join(thrd_t thr, int *res) {
if(mlibc::thread_join(thr, res) != 0) {
return thrd_error;
}
return thrd_success;
}
__attribute__((__noreturn__)) void thrd_exit(int) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
int mtx_init(mtx_t *mtx, int type) {
struct __mlibc_mutexattr attr;
mlibc::thread_mutexattr_init(&attr);
if(type & mtx_recursive) {
mlibc::thread_mutexattr_settype(&attr, __MLIBC_THREAD_MUTEX_RECURSIVE);
}
int res = mlibc::thread_mutex_init(mtx, &attr) == 0 ? thrd_success : thrd_error;
mlibc::thread_mutexattr_destroy(&attr);
return res;
}
void mtx_destroy(mtx_t *mtx) {
mlibc::thread_mutex_destroy(mtx);
}
int mtx_lock(mtx_t *mtx) {
return mlibc::thread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
}
int mtx_unlock(mtx_t *mtx) {
return mlibc::thread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;
}
int cnd_init(cnd_t *cond) {
return mlibc::thread_cond_init(cond, nullptr) == 0 ? thrd_success : thrd_error;
}
void cnd_destroy(cnd_t *cond) {
mlibc::thread_cond_destroy(cond);
}
int cnd_broadcast(cnd_t *cond) {
return mlibc::thread_cond_broadcast(cond) == 0 ? thrd_success : thrd_error;
}
int cnd_wait(cnd_t *cond, mtx_t *mtx) {
return mlibc::thread_cond_timedwait(cond, mtx, nullptr) == 0 ? thrd_success : thrd_error;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,25 @@
#include <bits/ensure.h>
#include <uchar.h>
#include <wchar.h>
size_t c32rtomb(char *__restrict s, char32_t c32, mbstate_t *__restrict ps) {
return wcrtomb(s, c32, ps);
}
size_t mbrtoc32(char32_t *__restrict pc32, const char *__restrict pmb, size_t max, mbstate_t *__restrict ps) {
static mbstate_t internal_state;
if(!ps)
ps = &internal_state;
if(!pmb)
return mbrtoc32(nullptr, "", 1, ps);
wchar_t wc;
size_t ret = mbrtowc(&wc, pmb, max, ps);
if (ret <= 4 && pc32)
*pc32 = wc;
return ret;
}
@@ -0,0 +1,790 @@
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <wctype.h>
#include <bits/ensure.h>
#include <mlibc/charcode.hpp>
#include <mlibc/debug.hpp>
namespace {
// All conversion functions mbrlen(), mbrtowc(), wcrtomb(),
// mbsrtowcs() and wcsrtombs() have an internal state.
__mlibc_mbstate mbrlen_state = __MLIBC_MBSTATE_INITIALIZER;
__mlibc_mbstate mbrtowc_state = __MLIBC_MBSTATE_INITIALIZER;
__mlibc_mbstate mbsrtowcs_state = __MLIBC_MBSTATE_INITIALIZER;
__mlibc_mbstate wcsrtombs_state = __MLIBC_MBSTATE_INITIALIZER;
} // namespace
wint_t btowc(int c) {
if(c == EOF)
return WEOF;
char nc = c;
auto cc = mlibc::current_charcode();
wchar_t wc;
if(auto e = cc->promote_wtranscode(nc, wc); e != mlibc::charcode_error::null)
return WEOF;
return wc;
}
int wctob(wint_t wc) {
// TODO: Revisit this once we have character encoding functions.
return wc;
}
int mbsinit(const mbstate_t *stp) {
if(!stp)
return -1;
return !stp->__progress && !stp->__shift;
}
size_t mbrlen(const char *__restrict mbs, size_t mb_limit, mbstate_t *__restrict stp) {
auto cc = mlibc::current_charcode();
wchar_t wc;
if(!stp)
stp = &mbrlen_state;
if(!mbs) {
*stp = __MLIBC_MBSTATE_INITIALIZER;
return 0;
}
mlibc::code_seq<const char> nseq{mbs, mbs + mb_limit};
mlibc::code_seq<wchar_t> wseq{&wc, &wc + 1};
if(auto e = cc->decode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return nseq.it - mbs;
}
size_t mbrtowc(wchar_t *__restrict wcp, const char *__restrict mbs, size_t mb_limit, mbstate_t *__restrict stp) {
auto cc = mlibc::current_charcode();
if(!stp)
stp = &mbrtowc_state;
if(!mbs) {
*stp = __MLIBC_MBSTATE_INITIALIZER;
return 0;
}
wchar_t temp = 0;
if(!wcp)
wcp = &temp;
mlibc::code_seq<const char> nseq{mbs, mbs + mb_limit};
mlibc::code_seq<wchar_t> wseq{wcp, wcp + 1};
if(auto e = cc->decode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null) {
if(e == mlibc::charcode_error::input_underflow)
return static_cast<size_t>(-2);
__ensure(e == mlibc::charcode_error::illegal_input);
errno = EILSEQ;
return static_cast<size_t>(-1);
}else{
if (*mbs) {
return nseq.it - mbs;
} else {
*stp = __MLIBC_MBSTATE_INITIALIZER;
*wcp = 0;
return 0;
}
}
}
size_t wcrtomb(char *__restrict mbs, wchar_t wc, mbstate_t *__restrict stp) {
auto cc = mlibc::current_charcode();
// wcrtomb() always takes a mbstate_t.
__ensure(stp);
// TODO: Implement the following case:
__ensure(mbs);
mlibc::code_seq<const wchar_t> wseq{&wc, &wc + 1};
mlibc::code_seq<char> nseq{mbs, mbs + MB_LEN_MAX};
if(auto e = cc->encode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null) {
__ensure(!"encode_wtranscode() errors are not handled");
__builtin_unreachable();
}else{
size_t n = nseq.it - mbs;
if(!n) // Null-terminate resulting wide string.
*mbs = 0;
return n;
}
}
size_t mbsrtowcs(wchar_t *__restrict wcs, const char **__restrict mbsp, size_t wc_limit, mbstate_t *__restrict stp) {
__ensure(mbsp);
auto cc = mlibc::current_charcode();
__mlibc_mbstate st = __MLIBC_MBSTATE_INITIALIZER;
mlibc::code_seq<const char> nseq{*mbsp, nullptr};
mlibc::code_seq<wchar_t> wseq{wcs, wcs + wc_limit};
if(!stp)
stp = &mbsrtowcs_state;
if(!wcs) {
size_t size;
if(auto e = cc->decode_wtranscode_length(nseq, &size, st); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return size;
}
if(auto e = cc->decode_wtranscode(nseq, wseq, st); e != mlibc::charcode_error::null) {
__ensure(!"decode_wtranscode() errors are not handled");
__builtin_unreachable();
}else{
size_t n = wseq.it - wcs;
if(n < wc_limit) // Null-terminate resulting wide string.
wcs[n] = 0;
*mbsp = nullptr;
return n;
}
}
size_t mbsnrtowcs(wchar_t *__restrict wcs, const char **__restrict mbsp, size_t mb_limit, size_t wc_limit, mbstate_t *__restrict stp) {
__ensure(mbsp);
auto cc = mlibc::current_charcode();
__mlibc_mbstate st = __MLIBC_MBSTATE_INITIALIZER;
mlibc::code_seq<const char> nseq{*mbsp, (*mbsp) + mb_limit};
mlibc::code_seq<wchar_t> wseq{wcs, wcs + wc_limit};
if(!stp)
stp = &mbsrtowcs_state;
if(!wcs) {
size_t size;
if(auto e = cc->decode_wtranscode_length(nseq, &size, st); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return size;
}
if(auto e = cc->decode_wtranscode(nseq, wseq, st); e != mlibc::charcode_error::null) {
__ensure(!"decode_wtranscode() errors are not handled");
__builtin_unreachable();
}else{
size_t n = wseq.it - wcs;
if(n < wc_limit) // Null-terminate resulting wide string.
wcs[n] = 0;
*mbsp = nullptr;
return n;
}
}
size_t wcsrtombs(char *__restrict mbs, const wchar_t **__restrict wcsp, size_t mb_limit, mbstate_t *__restrict stp) {
__ensure(wcsp && "wcsrtombs() with null input");
auto cc = mlibc::current_charcode();
mlibc::code_seq<const wchar_t> wseq{*wcsp, nullptr};
if(!stp)
stp = &wcsrtombs_state;
if(!mbs) {
size_t size;
if(auto e = cc->encode_wtranscode_length(wseq, &size, *stp); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return size;
}
mlibc::code_seq<char> nseq{mbs, mbs + mb_limit};
if(auto e = cc->encode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null) {
__ensure(!"encode_wtranscode() errors are not handled");
__builtin_unreachable();
}else{
*wcsp = wseq.it;
size_t n = nseq.it - mbs;
if(n < mb_limit) // Null-terminate resulting narrow string.
mbs[n] = 0;
return n;
}
}
size_t wcsnrtombs(char *__restrict mbs, const wchar_t **__restrict wcsp, size_t wc_limit, size_t mb_limit, mbstate_t *__restrict stp) {
__ensure(wcsp && "wcsrtombs() with null input");
auto cc = mlibc::current_charcode();
mlibc::code_seq<char> nseq{mbs, mbs + mb_limit};
mlibc::code_seq<const wchar_t> wseq{*wcsp, (*wcsp) + wc_limit};
if(!stp)
stp = &wcsrtombs_state;
if(!mbs) {
size_t size;
if(auto e = cc->encode_wtranscode_length(wseq, &size, *stp); e != mlibc::charcode_error::null)
__ensure(!"decode_wtranscode() errors are not handled");
return size;
}
if(auto e = cc->encode_wtranscode(nseq, wseq, *stp); e != mlibc::charcode_error::null) {
__ensure(!"encode_wtranscode() errors are not handled");
__builtin_unreachable();
}else{
*wcsp = wseq.it;
size_t n = nseq.it - mbs;
if(n < mb_limit) // Null-terminate resulting narrow string.
mbs[n] = 0;
return n;
}
}
/*
* The code in this anonymous namespace and the wcwidth function below
* are taken from https://github.com/termux/wcwidth/, under the following license:
*
* Copyright (C) Fredrik Fornwall 2016.
* Distributed under the MIT License.
*
* Implementation of wcwidth(3) as a C port of:
* https://github.com/jquast/wcwidth
*
* Report issues at:
* https://github.com/termux/wcwidth
*/
namespace {
struct width_interval {
int start;
int end;
};
// From https://github.com/jquast/wcwidth/blob/master/wcwidth/table_zero.py
// at commit b29897e5a1b403a0e36f7fc991614981cbc42475 (2020-07-14):
struct width_interval ZERO_WIDTH[] = {
{0x00300, 0x0036f}, // Combining Grave Accent ..Combining Latin Small Le
{0x00483, 0x00489}, // Combining Cyrillic Titlo..Combining Cyrillic Milli
{0x00591, 0x005bd}, // Hebrew Accent Etnahta ..Hebrew Point Meteg
{0x005bf, 0x005bf}, // Hebrew Point Rafe ..Hebrew Point Rafe
{0x005c1, 0x005c2}, // Hebrew Point Shin Dot ..Hebrew Point Sin Dot
{0x005c4, 0x005c5}, // Hebrew Mark Upper Dot ..Hebrew Mark Lower Dot
{0x005c7, 0x005c7}, // Hebrew Point Qamats Qata..Hebrew Point Qamats Qata
{0x00610, 0x0061a}, // Arabic Sign Sallallahou ..Arabic Small Kasra
{0x0064b, 0x0065f}, // Arabic Fathatan ..Arabic Wavy Hamza Below
{0x00670, 0x00670}, // Arabic Letter Superscrip..Arabic Letter Superscrip
{0x006d6, 0x006dc}, // Arabic Small High Ligatu..Arabic Small High Seen
{0x006df, 0x006e4}, // Arabic Small High Rounde..Arabic Small High Madda
{0x006e7, 0x006e8}, // Arabic Small High Yeh ..Arabic Small High Noon
{0x006ea, 0x006ed}, // Arabic Empty Centre Low ..Arabic Small Low Meem
{0x00711, 0x00711}, // Syriac Letter Superscrip..Syriac Letter Superscrip
{0x00730, 0x0074a}, // Syriac Pthaha Above ..Syriac Barrekh
{0x007a6, 0x007b0}, // Thaana Abafili ..Thaana Sukun
{0x007eb, 0x007f3}, // Nko Combining Short High..Nko Combining Double Dot
{0x007fd, 0x007fd}, // Nko Dantayalan ..Nko Dantayalan
{0x00816, 0x00819}, // Samaritan Mark In ..Samaritan Mark Dagesh
{0x0081b, 0x00823}, // Samaritan Mark Epentheti..Samaritan Vowel Sign A
{0x00825, 0x00827}, // Samaritan Vowel Sign Sho..Samaritan Vowel Sign U
{0x00829, 0x0082d}, // Samaritan Vowel Sign Lon..Samaritan Mark Nequdaa
{0x00859, 0x0085b}, // Mandaic Affrication Mark..Mandaic Gemination Mark
{0x008d3, 0x008e1}, // Arabic Small Low Waw ..Arabic Small High Sign S
{0x008e3, 0x00902}, // Arabic Turned Damma Belo..Devanagari Sign Anusvara
{0x0093a, 0x0093a}, // Devanagari Vowel Sign Oe..Devanagari Vowel Sign Oe
{0x0093c, 0x0093c}, // Devanagari Sign Nukta ..Devanagari Sign Nukta
{0x00941, 0x00948}, // Devanagari Vowel Sign U ..Devanagari Vowel Sign Ai
{0x0094d, 0x0094d}, // Devanagari Sign Virama ..Devanagari Sign Virama
{0x00951, 0x00957}, // Devanagari Stress Sign U..Devanagari Vowel Sign Uu
{0x00962, 0x00963}, // Devanagari Vowel Sign Vo..Devanagari Vowel Sign Vo
{0x00981, 0x00981}, // Bengali Sign Candrabindu..Bengali Sign Candrabindu
{0x009bc, 0x009bc}, // Bengali Sign Nukta ..Bengali Sign Nukta
{0x009c1, 0x009c4}, // Bengali Vowel Sign U ..Bengali Vowel Sign Vocal
{0x009cd, 0x009cd}, // Bengali Sign Virama ..Bengali Sign Virama
{0x009e2, 0x009e3}, // Bengali Vowel Sign Vocal..Bengali Vowel Sign Vocal
{0x009fe, 0x009fe}, // Bengali Sandhi Mark ..Bengali Sandhi Mark
{0x00a01, 0x00a02}, // Gurmukhi Sign Adak Bindi..Gurmukhi Sign Bindi
{0x00a3c, 0x00a3c}, // Gurmukhi Sign Nukta ..Gurmukhi Sign Nukta
{0x00a41, 0x00a42}, // Gurmukhi Vowel Sign U ..Gurmukhi Vowel Sign Uu
{0x00a47, 0x00a48}, // Gurmukhi Vowel Sign Ee ..Gurmukhi Vowel Sign Ai
{0x00a4b, 0x00a4d}, // Gurmukhi Vowel Sign Oo ..Gurmukhi Sign Virama
{0x00a51, 0x00a51}, // Gurmukhi Sign Udaat ..Gurmukhi Sign Udaat
{0x00a70, 0x00a71}, // Gurmukhi Tippi ..Gurmukhi Addak
{0x00a75, 0x00a75}, // Gurmukhi Sign Yakash ..Gurmukhi Sign Yakash
{0x00a81, 0x00a82}, // Gujarati Sign Candrabind..Gujarati Sign Anusvara
{0x00abc, 0x00abc}, // Gujarati Sign Nukta ..Gujarati Sign Nukta
{0x00ac1, 0x00ac5}, // Gujarati Vowel Sign U ..Gujarati Vowel Sign Cand
{0x00ac7, 0x00ac8}, // Gujarati Vowel Sign E ..Gujarati Vowel Sign Ai
{0x00acd, 0x00acd}, // Gujarati Sign Virama ..Gujarati Sign Virama
{0x00ae2, 0x00ae3}, // Gujarati Vowel Sign Voca..Gujarati Vowel Sign Voca
{0x00afa, 0x00aff}, // Gujarati Sign Sukun ..Gujarati Sign Two-circle
{0x00b01, 0x00b01}, // Oriya Sign Candrabindu ..Oriya Sign Candrabindu
{0x00b3c, 0x00b3c}, // Oriya Sign Nukta ..Oriya Sign Nukta
{0x00b3f, 0x00b3f}, // Oriya Vowel Sign I ..Oriya Vowel Sign I
{0x00b41, 0x00b44}, // Oriya Vowel Sign U ..Oriya Vowel Sign Vocalic
{0x00b4d, 0x00b4d}, // Oriya Sign Virama ..Oriya Sign Virama
{0x00b55, 0x00b56}, // (nil) ..Oriya Ai Length Mark
{0x00b62, 0x00b63}, // Oriya Vowel Sign Vocalic..Oriya Vowel Sign Vocalic
{0x00b82, 0x00b82}, // Tamil Sign Anusvara ..Tamil Sign Anusvara
{0x00bc0, 0x00bc0}, // Tamil Vowel Sign Ii ..Tamil Vowel Sign Ii
{0x00bcd, 0x00bcd}, // Tamil Sign Virama ..Tamil Sign Virama
{0x00c00, 0x00c00}, // Telugu Sign Combining Ca..Telugu Sign Combining Ca
{0x00c04, 0x00c04}, // Telugu Sign Combining An..Telugu Sign Combining An
{0x00c3e, 0x00c40}, // Telugu Vowel Sign Aa ..Telugu Vowel Sign Ii
{0x00c46, 0x00c48}, // Telugu Vowel Sign E ..Telugu Vowel Sign Ai
{0x00c4a, 0x00c4d}, // Telugu Vowel Sign O ..Telugu Sign Virama
{0x00c55, 0x00c56}, // Telugu Length Mark ..Telugu Ai Length Mark
{0x00c62, 0x00c63}, // Telugu Vowel Sign Vocali..Telugu Vowel Sign Vocali
{0x00c81, 0x00c81}, // Kannada Sign Candrabindu..Kannada Sign Candrabindu
{0x00cbc, 0x00cbc}, // Kannada Sign Nukta ..Kannada Sign Nukta
{0x00cbf, 0x00cbf}, // Kannada Vowel Sign I ..Kannada Vowel Sign I
{0x00cc6, 0x00cc6}, // Kannada Vowel Sign E ..Kannada Vowel Sign E
{0x00ccc, 0x00ccd}, // Kannada Vowel Sign Au ..Kannada Sign Virama
{0x00ce2, 0x00ce3}, // Kannada Vowel Sign Vocal..Kannada Vowel Sign Vocal
{0x00d00, 0x00d01}, // Malayalam Sign Combining..Malayalam Sign Candrabin
{0x00d3b, 0x00d3c}, // Malayalam Sign Vertical ..Malayalam Sign Circular
{0x00d41, 0x00d44}, // Malayalam Vowel Sign U ..Malayalam Vowel Sign Voc
{0x00d4d, 0x00d4d}, // Malayalam Sign Virama ..Malayalam Sign Virama
{0x00d62, 0x00d63}, // Malayalam Vowel Sign Voc..Malayalam Vowel Sign Voc
{0x00d81, 0x00d81}, // (nil) ..(nil)
{0x00dca, 0x00dca}, // Sinhala Sign Al-lakuna ..Sinhala Sign Al-lakuna
{0x00dd2, 0x00dd4}, // Sinhala Vowel Sign Ketti..Sinhala Vowel Sign Ketti
{0x00dd6, 0x00dd6}, // Sinhala Vowel Sign Diga ..Sinhala Vowel Sign Diga
{0x00e31, 0x00e31}, // Thai Character Mai Han-a..Thai Character Mai Han-a
{0x00e34, 0x00e3a}, // Thai Character Sara I ..Thai Character Phinthu
{0x00e47, 0x00e4e}, // Thai Character Maitaikhu..Thai Character Yamakkan
{0x00eb1, 0x00eb1}, // Lao Vowel Sign Mai Kan ..Lao Vowel Sign Mai Kan
{0x00eb4, 0x00ebc}, // Lao Vowel Sign I ..Lao Semivowel Sign Lo
{0x00ec8, 0x00ecd}, // Lao Tone Mai Ek ..Lao Niggahita
{0x00f18, 0x00f19}, // Tibetan Astrological Sig..Tibetan Astrological Sig
{0x00f35, 0x00f35}, // Tibetan Mark Ngas Bzung ..Tibetan Mark Ngas Bzung
{0x00f37, 0x00f37}, // Tibetan Mark Ngas Bzung ..Tibetan Mark Ngas Bzung
{0x00f39, 0x00f39}, // Tibetan Mark Tsa -phru ..Tibetan Mark Tsa -phru
{0x00f71, 0x00f7e}, // Tibetan Vowel Sign Aa ..Tibetan Sign Rjes Su Nga
{0x00f80, 0x00f84}, // Tibetan Vowel Sign Rever..Tibetan Mark Halanta
{0x00f86, 0x00f87}, // Tibetan Sign Lci Rtags ..Tibetan Sign Yang Rtags
{0x00f8d, 0x00f97}, // Tibetan Subjoined Sign L..Tibetan Subjoined Letter
{0x00f99, 0x00fbc}, // Tibetan Subjoined Letter..Tibetan Subjoined Letter
{0x00fc6, 0x00fc6}, // Tibetan Symbol Padma Gda..Tibetan Symbol Padma Gda
{0x0102d, 0x01030}, // Myanmar Vowel Sign I ..Myanmar Vowel Sign Uu
{0x01032, 0x01037}, // Myanmar Vowel Sign Ai ..Myanmar Sign Dot Below
{0x01039, 0x0103a}, // Myanmar Sign Virama ..Myanmar Sign Asat
{0x0103d, 0x0103e}, // Myanmar Consonant Sign M..Myanmar Consonant Sign M
{0x01058, 0x01059}, // Myanmar Vowel Sign Vocal..Myanmar Vowel Sign Vocal
{0x0105e, 0x01060}, // Myanmar Consonant Sign M..Myanmar Consonant Sign M
{0x01071, 0x01074}, // Myanmar Vowel Sign Geba ..Myanmar Vowel Sign Kayah
{0x01082, 0x01082}, // Myanmar Consonant Sign S..Myanmar Consonant Sign S
{0x01085, 0x01086}, // Myanmar Vowel Sign Shan ..Myanmar Vowel Sign Shan
{0x0108d, 0x0108d}, // Myanmar Sign Shan Counci..Myanmar Sign Shan Counci
{0x0109d, 0x0109d}, // Myanmar Vowel Sign Aiton..Myanmar Vowel Sign Aiton
{0x0135d, 0x0135f}, // Ethiopic Combining Gemin..Ethiopic Combining Gemin
{0x01712, 0x01714}, // Tagalog Vowel Sign I ..Tagalog Sign Virama
{0x01732, 0x01734}, // Hanunoo Vowel Sign I ..Hanunoo Sign Pamudpod
{0x01752, 0x01753}, // Buhid Vowel Sign I ..Buhid Vowel Sign U
{0x01772, 0x01773}, // Tagbanwa Vowel Sign I ..Tagbanwa Vowel Sign U
{0x017b4, 0x017b5}, // Khmer Vowel Inherent Aq ..Khmer Vowel Inherent Aa
{0x017b7, 0x017bd}, // Khmer Vowel Sign I ..Khmer Vowel Sign Ua
{0x017c6, 0x017c6}, // Khmer Sign Nikahit ..Khmer Sign Nikahit
{0x017c9, 0x017d3}, // Khmer Sign Muusikatoan ..Khmer Sign Bathamasat
{0x017dd, 0x017dd}, // Khmer Sign Atthacan ..Khmer Sign Atthacan
{0x0180b, 0x0180d}, // Mongolian Free Variation..Mongolian Free Variation
{0x01885, 0x01886}, // Mongolian Letter Ali Gal..Mongolian Letter Ali Gal
{0x018a9, 0x018a9}, // Mongolian Letter Ali Gal..Mongolian Letter Ali Gal
{0x01920, 0x01922}, // Limbu Vowel Sign A ..Limbu Vowel Sign U
{0x01927, 0x01928}, // Limbu Vowel Sign E ..Limbu Vowel Sign O
{0x01932, 0x01932}, // Limbu Small Letter Anusv..Limbu Small Letter Anusv
{0x01939, 0x0193b}, // Limbu Sign Mukphreng ..Limbu Sign Sa-i
{0x01a17, 0x01a18}, // Buginese Vowel Sign I ..Buginese Vowel Sign U
{0x01a1b, 0x01a1b}, // Buginese Vowel Sign Ae ..Buginese Vowel Sign Ae
{0x01a56, 0x01a56}, // Tai Tham Consonant Sign ..Tai Tham Consonant Sign
{0x01a58, 0x01a5e}, // Tai Tham Sign Mai Kang L..Tai Tham Consonant Sign
{0x01a60, 0x01a60}, // Tai Tham Sign Sakot ..Tai Tham Sign Sakot
{0x01a62, 0x01a62}, // Tai Tham Vowel Sign Mai ..Tai Tham Vowel Sign Mai
{0x01a65, 0x01a6c}, // Tai Tham Vowel Sign I ..Tai Tham Vowel Sign Oa B
{0x01a73, 0x01a7c}, // Tai Tham Vowel Sign Oa A..Tai Tham Sign Khuen-lue
{0x01a7f, 0x01a7f}, // Tai Tham Combining Crypt..Tai Tham Combining Crypt
{0x01ab0, 0x01ac0}, // Combining Doubled Circum..(nil)
{0x01b00, 0x01b03}, // Balinese Sign Ulu Ricem ..Balinese Sign Surang
{0x01b34, 0x01b34}, // Balinese Sign Rerekan ..Balinese Sign Rerekan
{0x01b36, 0x01b3a}, // Balinese Vowel Sign Ulu ..Balinese Vowel Sign Ra R
{0x01b3c, 0x01b3c}, // Balinese Vowel Sign La L..Balinese Vowel Sign La L
{0x01b42, 0x01b42}, // Balinese Vowel Sign Pepe..Balinese Vowel Sign Pepe
{0x01b6b, 0x01b73}, // Balinese Musical Symbol ..Balinese Musical Symbol
{0x01b80, 0x01b81}, // Sundanese Sign Panyecek ..Sundanese Sign Panglayar
{0x01ba2, 0x01ba5}, // Sundanese Consonant Sign..Sundanese Vowel Sign Pan
{0x01ba8, 0x01ba9}, // Sundanese Vowel Sign Pam..Sundanese Vowel Sign Pan
{0x01bab, 0x01bad}, // Sundanese Sign Virama ..Sundanese Consonant Sign
{0x01be6, 0x01be6}, // Batak Sign Tompi ..Batak Sign Tompi
{0x01be8, 0x01be9}, // Batak Vowel Sign Pakpak ..Batak Vowel Sign Ee
{0x01bed, 0x01bed}, // Batak Vowel Sign Karo O ..Batak Vowel Sign Karo O
{0x01bef, 0x01bf1}, // Batak Vowel Sign U For S..Batak Consonant Sign H
{0x01c2c, 0x01c33}, // Lepcha Vowel Sign E ..Lepcha Consonant Sign T
{0x01c36, 0x01c37}, // Lepcha Sign Ran ..Lepcha Sign Nukta
{0x01cd0, 0x01cd2}, // Vedic Tone Karshana ..Vedic Tone Prenkha
{0x01cd4, 0x01ce0}, // Vedic Sign Yajurvedic Mi..Vedic Tone Rigvedic Kash
{0x01ce2, 0x01ce8}, // Vedic Sign Visarga Svari..Vedic Sign Visarga Anuda
{0x01ced, 0x01ced}, // Vedic Sign Tiryak ..Vedic Sign Tiryak
{0x01cf4, 0x01cf4}, // Vedic Tone Candra Above ..Vedic Tone Candra Above
{0x01cf8, 0x01cf9}, // Vedic Tone Ring Above ..Vedic Tone Double Ring A
{0x01dc0, 0x01df9}, // Combining Dotted Grave A..Combining Wide Inverted
{0x01dfb, 0x01dff}, // Combining Deletion Mark ..Combining Right Arrowhea
{0x020d0, 0x020f0}, // Combining Left Harpoon A..Combining Asterisk Above
{0x02cef, 0x02cf1}, // Coptic Combining Ni Abov..Coptic Combining Spiritu
{0x02d7f, 0x02d7f}, // Tifinagh Consonant Joine..Tifinagh Consonant Joine
{0x02de0, 0x02dff}, // Combining Cyrillic Lette..Combining Cyrillic Lette
{0x0302a, 0x0302d}, // Ideographic Level Tone M..Ideographic Entering Ton
{0x03099, 0x0309a}, // Combining Katakana-hirag..Combining Katakana-hirag
{0x0a66f, 0x0a672}, // Combining Cyrillic Vzmet..Combining Cyrillic Thous
{0x0a674, 0x0a67d}, // Combining Cyrillic Lette..Combining Cyrillic Payer
{0x0a69e, 0x0a69f}, // Combining Cyrillic Lette..Combining Cyrillic Lette
{0x0a6f0, 0x0a6f1}, // Bamum Combining Mark Koq..Bamum Combining Mark Tuk
{0x0a802, 0x0a802}, // Syloti Nagri Sign Dvisva..Syloti Nagri Sign Dvisva
{0x0a806, 0x0a806}, // Syloti Nagri Sign Hasant..Syloti Nagri Sign Hasant
{0x0a80b, 0x0a80b}, // Syloti Nagri Sign Anusva..Syloti Nagri Sign Anusva
{0x0a825, 0x0a826}, // Syloti Nagri Vowel Sign ..Syloti Nagri Vowel Sign
{0x0a82c, 0x0a82c}, // (nil) ..(nil)
{0x0a8c4, 0x0a8c5}, // Saurashtra Sign Virama ..Saurashtra Sign Candrabi
{0x0a8e0, 0x0a8f1}, // Combining Devanagari Dig..Combining Devanagari Sig
{0x0a8ff, 0x0a8ff}, // Devanagari Vowel Sign Ay..Devanagari Vowel Sign Ay
{0x0a926, 0x0a92d}, // Kayah Li Vowel Ue ..Kayah Li Tone Calya Plop
{0x0a947, 0x0a951}, // Rejang Vowel Sign I ..Rejang Consonant Sign R
{0x0a980, 0x0a982}, // Javanese Sign Panyangga ..Javanese Sign Layar
{0x0a9b3, 0x0a9b3}, // Javanese Sign Cecak Telu..Javanese Sign Cecak Telu
{0x0a9b6, 0x0a9b9}, // Javanese Vowel Sign Wulu..Javanese Vowel Sign Suku
{0x0a9bc, 0x0a9bd}, // Javanese Vowel Sign Pepe..Javanese Consonant Sign
{0x0a9e5, 0x0a9e5}, // Myanmar Sign Shan Saw ..Myanmar Sign Shan Saw
{0x0aa29, 0x0aa2e}, // Cham Vowel Sign Aa ..Cham Vowel Sign Oe
{0x0aa31, 0x0aa32}, // Cham Vowel Sign Au ..Cham Vowel Sign Ue
{0x0aa35, 0x0aa36}, // Cham Consonant Sign La ..Cham Consonant Sign Wa
{0x0aa43, 0x0aa43}, // Cham Consonant Sign Fina..Cham Consonant Sign Fina
{0x0aa4c, 0x0aa4c}, // Cham Consonant Sign Fina..Cham Consonant Sign Fina
{0x0aa7c, 0x0aa7c}, // Myanmar Sign Tai Laing T..Myanmar Sign Tai Laing T
{0x0aab0, 0x0aab0}, // Tai Viet Mai Kang ..Tai Viet Mai Kang
{0x0aab2, 0x0aab4}, // Tai Viet Vowel I ..Tai Viet Vowel U
{0x0aab7, 0x0aab8}, // Tai Viet Mai Khit ..Tai Viet Vowel Ia
{0x0aabe, 0x0aabf}, // Tai Viet Vowel Am ..Tai Viet Tone Mai Ek
{0x0aac1, 0x0aac1}, // Tai Viet Tone Mai Tho ..Tai Viet Tone Mai Tho
{0x0aaec, 0x0aaed}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign
{0x0aaf6, 0x0aaf6}, // Meetei Mayek Virama ..Meetei Mayek Virama
{0x0abe5, 0x0abe5}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign
{0x0abe8, 0x0abe8}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign
{0x0abed, 0x0abed}, // Meetei Mayek Apun Iyek ..Meetei Mayek Apun Iyek
{0x0fb1e, 0x0fb1e}, // Hebrew Point Judeo-spani..Hebrew Point Judeo-spani
{0x0fe00, 0x0fe0f}, // Variation Selector-1 ..Variation Selector-16
{0x0fe20, 0x0fe2f}, // Combining Ligature Left ..Combining Cyrillic Titlo
{0x101fd, 0x101fd}, // Phaistos Disc Sign Combi..Phaistos Disc Sign Combi
{0x102e0, 0x102e0}, // Coptic Epact Thousands M..Coptic Epact Thousands M
{0x10376, 0x1037a}, // Combining Old Permic Let..Combining Old Permic Let
{0x10a01, 0x10a03}, // Kharoshthi Vowel Sign I ..Kharoshthi Vowel Sign Vo
{0x10a05, 0x10a06}, // Kharoshthi Vowel Sign E ..Kharoshthi Vowel Sign O
{0x10a0c, 0x10a0f}, // Kharoshthi Vowel Length ..Kharoshthi Sign Visarga
{0x10a38, 0x10a3a}, // Kharoshthi Sign Bar Abov..Kharoshthi Sign Dot Belo
{0x10a3f, 0x10a3f}, // Kharoshthi Virama ..Kharoshthi Virama
{0x10ae5, 0x10ae6}, // Manichaean Abbreviation ..Manichaean Abbreviation
{0x10d24, 0x10d27}, // Hanifi Rohingya Sign Har..Hanifi Rohingya Sign Tas
{0x10eab, 0x10eac}, // (nil) ..(nil)
{0x10f46, 0x10f50}, // Sogdian Combining Dot Be..Sogdian Combining Stroke
{0x11001, 0x11001}, // Brahmi Sign Anusvara ..Brahmi Sign Anusvara
{0x11038, 0x11046}, // Brahmi Vowel Sign Aa ..Brahmi Virama
{0x1107f, 0x11081}, // Brahmi Number Joiner ..Kaithi Sign Anusvara
{0x110b3, 0x110b6}, // Kaithi Vowel Sign U ..Kaithi Vowel Sign Ai
{0x110b9, 0x110ba}, // Kaithi Sign Virama ..Kaithi Sign Nukta
{0x11100, 0x11102}, // Chakma Sign Candrabindu ..Chakma Sign Visarga
{0x11127, 0x1112b}, // Chakma Vowel Sign A ..Chakma Vowel Sign Uu
{0x1112d, 0x11134}, // Chakma Vowel Sign Ai ..Chakma Maayyaa
{0x11173, 0x11173}, // Mahajani Sign Nukta ..Mahajani Sign Nukta
{0x11180, 0x11181}, // Sharada Sign Candrabindu..Sharada Sign Anusvara
{0x111b6, 0x111be}, // Sharada Vowel Sign U ..Sharada Vowel Sign O
{0x111c9, 0x111cc}, // Sharada Sandhi Mark ..Sharada Extra Short Vowe
{0x111cf, 0x111cf}, // (nil) ..(nil)
{0x1122f, 0x11231}, // Khojki Vowel Sign U ..Khojki Vowel Sign Ai
{0x11234, 0x11234}, // Khojki Sign Anusvara ..Khojki Sign Anusvara
{0x11236, 0x11237}, // Khojki Sign Nukta ..Khojki Sign Shadda
{0x1123e, 0x1123e}, // Khojki Sign Sukun ..Khojki Sign Sukun
{0x112df, 0x112df}, // Khudawadi Sign Anusvara ..Khudawadi Sign Anusvara
{0x112e3, 0x112ea}, // Khudawadi Vowel Sign U ..Khudawadi Sign Virama
{0x11300, 0x11301}, // Grantha Sign Combining A..Grantha Sign Candrabindu
{0x1133b, 0x1133c}, // Combining Bindu Below ..Grantha Sign Nukta
{0x11340, 0x11340}, // Grantha Vowel Sign Ii ..Grantha Vowel Sign Ii
{0x11366, 0x1136c}, // Combining Grantha Digit ..Combining Grantha Digit
{0x11370, 0x11374}, // Combining Grantha Letter..Combining Grantha Letter
{0x11438, 0x1143f}, // Newa Vowel Sign U ..Newa Vowel Sign Ai
{0x11442, 0x11444}, // Newa Sign Virama ..Newa Sign Anusvara
{0x11446, 0x11446}, // Newa Sign Nukta ..Newa Sign Nukta
{0x1145e, 0x1145e}, // Newa Sandhi Mark ..Newa Sandhi Mark
{0x114b3, 0x114b8}, // Tirhuta Vowel Sign U ..Tirhuta Vowel Sign Vocal
{0x114ba, 0x114ba}, // Tirhuta Vowel Sign Short..Tirhuta Vowel Sign Short
{0x114bf, 0x114c0}, // Tirhuta Sign Candrabindu..Tirhuta Sign Anusvara
{0x114c2, 0x114c3}, // Tirhuta Sign Virama ..Tirhuta Sign Nukta
{0x115b2, 0x115b5}, // Siddham Vowel Sign U ..Siddham Vowel Sign Vocal
{0x115bc, 0x115bd}, // Siddham Sign Candrabindu..Siddham Sign Anusvara
{0x115bf, 0x115c0}, // Siddham Sign Virama ..Siddham Sign Nukta
{0x115dc, 0x115dd}, // Siddham Vowel Sign Alter..Siddham Vowel Sign Alter
{0x11633, 0x1163a}, // Modi Vowel Sign U ..Modi Vowel Sign Ai
{0x1163d, 0x1163d}, // Modi Sign Anusvara ..Modi Sign Anusvara
{0x1163f, 0x11640}, // Modi Sign Virama ..Modi Sign Ardhacandra
{0x116ab, 0x116ab}, // Takri Sign Anusvara ..Takri Sign Anusvara
{0x116ad, 0x116ad}, // Takri Vowel Sign Aa ..Takri Vowel Sign Aa
{0x116b0, 0x116b5}, // Takri Vowel Sign U ..Takri Vowel Sign Au
{0x116b7, 0x116b7}, // Takri Sign Nukta ..Takri Sign Nukta
{0x1171d, 0x1171f}, // Ahom Consonant Sign Medi..Ahom Consonant Sign Medi
{0x11722, 0x11725}, // Ahom Vowel Sign I ..Ahom Vowel Sign Uu
{0x11727, 0x1172b}, // Ahom Vowel Sign Aw ..Ahom Sign Killer
{0x1182f, 0x11837}, // Dogra Vowel Sign U ..Dogra Sign Anusvara
{0x11839, 0x1183a}, // Dogra Sign Virama ..Dogra Sign Nukta
{0x1193b, 0x1193c}, // (nil) ..(nil)
{0x1193e, 0x1193e}, // (nil) ..(nil)
{0x11943, 0x11943}, // (nil) ..(nil)
{0x119d4, 0x119d7}, // Nandinagari Vowel Sign U..Nandinagari Vowel Sign V
{0x119da, 0x119db}, // Nandinagari Vowel Sign E..Nandinagari Vowel Sign A
{0x119e0, 0x119e0}, // Nandinagari Sign Virama ..Nandinagari Sign Virama
{0x11a01, 0x11a0a}, // Zanabazar Square Vowel S..Zanabazar Square Vowel L
{0x11a33, 0x11a38}, // Zanabazar Square Final C..Zanabazar Square Sign An
{0x11a3b, 0x11a3e}, // Zanabazar Square Cluster..Zanabazar Square Cluster
{0x11a47, 0x11a47}, // Zanabazar Square Subjoin..Zanabazar Square Subjoin
{0x11a51, 0x11a56}, // Soyombo Vowel Sign I ..Soyombo Vowel Sign Oe
{0x11a59, 0x11a5b}, // Soyombo Vowel Sign Vocal..Soyombo Vowel Length Mar
{0x11a8a, 0x11a96}, // Soyombo Final Consonant ..Soyombo Sign Anusvara
{0x11a98, 0x11a99}, // Soyombo Gemination Mark ..Soyombo Subjoiner
{0x11c30, 0x11c36}, // Bhaiksuki Vowel Sign I ..Bhaiksuki Vowel Sign Voc
{0x11c38, 0x11c3d}, // Bhaiksuki Vowel Sign E ..Bhaiksuki Sign Anusvara
{0x11c3f, 0x11c3f}, // Bhaiksuki Sign Virama ..Bhaiksuki Sign Virama
{0x11c92, 0x11ca7}, // Marchen Subjoined Letter..Marchen Subjoined Letter
{0x11caa, 0x11cb0}, // Marchen Subjoined Letter..Marchen Vowel Sign Aa
{0x11cb2, 0x11cb3}, // Marchen Vowel Sign U ..Marchen Vowel Sign E
{0x11cb5, 0x11cb6}, // Marchen Sign Anusvara ..Marchen Sign Candrabindu
{0x11d31, 0x11d36}, // Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign
{0x11d3a, 0x11d3a}, // Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign
{0x11d3c, 0x11d3d}, // Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign
{0x11d3f, 0x11d45}, // Masaram Gondi Vowel Sign..Masaram Gondi Virama
{0x11d47, 0x11d47}, // Masaram Gondi Ra-kara ..Masaram Gondi Ra-kara
{0x11d90, 0x11d91}, // Gunjala Gondi Vowel Sign..Gunjala Gondi Vowel Sign
{0x11d95, 0x11d95}, // Gunjala Gondi Sign Anusv..Gunjala Gondi Sign Anusv
{0x11d97, 0x11d97}, // Gunjala Gondi Virama ..Gunjala Gondi Virama
{0x11ef3, 0x11ef4}, // Makasar Vowel Sign I ..Makasar Vowel Sign U
{0x16af0, 0x16af4}, // Bassa Vah Combining High..Bassa Vah Combining High
{0x16b30, 0x16b36}, // Pahawh Hmong Mark Cim Tu..Pahawh Hmong Mark Cim Ta
{0x16f4f, 0x16f4f}, // Miao Sign Consonant Modi..Miao Sign Consonant Modi
{0x16f8f, 0x16f92}, // Miao Tone Right ..Miao Tone Below
{0x16fe4, 0x16fe4}, // (nil) ..(nil)
{0x1bc9d, 0x1bc9e}, // Duployan Thick Letter Se..Duployan Double Mark
{0x1d167, 0x1d169}, // Musical Symbol Combining..Musical Symbol Combining
{0x1d17b, 0x1d182}, // Musical Symbol Combining..Musical Symbol Combining
{0x1d185, 0x1d18b}, // Musical Symbol Combining..Musical Symbol Combining
{0x1d1aa, 0x1d1ad}, // Musical Symbol Combining..Musical Symbol Combining
{0x1d242, 0x1d244}, // Combining Greek Musical ..Combining Greek Musical
{0x1da00, 0x1da36}, // Signwriting Head Rim ..Signwriting Air Sucking
{0x1da3b, 0x1da6c}, // Signwriting Mouth Closed..Signwriting Excitement
{0x1da75, 0x1da75}, // Signwriting Upper Body T..Signwriting Upper Body T
{0x1da84, 0x1da84}, // Signwriting Location Hea..Signwriting Location Hea
{0x1da9b, 0x1da9f}, // Signwriting Fill Modifie..Signwriting Fill Modifie
{0x1daa1, 0x1daaf}, // Signwriting Rotation Mod..Signwriting Rotation Mod
{0x1e000, 0x1e006}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e008, 0x1e018}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e01b, 0x1e021}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e023, 0x1e024}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e026, 0x1e02a}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e130, 0x1e136}, // Nyiakeng Puachue Hmong T..Nyiakeng Puachue Hmong T
{0x1e2ec, 0x1e2ef}, // Wancho Tone Tup ..Wancho Tone Koini
{0x1e8d0, 0x1e8d6}, // Mende Kikakui Combining ..Mende Kikakui Combining
{0x1e944, 0x1e94a}, // Adlam Alif Lengthener ..Adlam Nukta
{0xe0100, 0xe01ef}, // Variation Selector-17 ..Variation Selector-256
};
// https://github.com/jquast/wcwidth/blob/master/wcwidth/table_wide.py
// at commit b29897e5a1b403a0e36f7fc991614981cbc42475 (2020-07-14):
struct width_interval WIDE_EASTASIAN[] = {
{0x01100, 0x0115f}, // Hangul Choseong Kiyeok ..Hangul Choseong Filler
{0x0231a, 0x0231b}, // Watch ..Hourglass
{0x02329, 0x0232a}, // Left-pointing Angle Brac..Right-pointing Angle Bra
{0x023e9, 0x023ec}, // Black Right-pointing Dou..Black Down-pointing Doub
{0x023f0, 0x023f0}, // Alarm Clock ..Alarm Clock
{0x023f3, 0x023f3}, // Hourglass With Flowing S..Hourglass With Flowing S
{0x025fd, 0x025fe}, // White Medium Small Squar..Black Medium Small Squar
{0x02614, 0x02615}, // Umbrella With Rain Drops..Hot Beverage
{0x02648, 0x02653}, // Aries ..Pisces
{0x0267f, 0x0267f}, // Wheelchair Symbol ..Wheelchair Symbol
{0x02693, 0x02693}, // Anchor ..Anchor
{0x026a1, 0x026a1}, // High Voltage Sign ..High Voltage Sign
{0x026aa, 0x026ab}, // Medium White Circle ..Medium Black Circle
{0x026bd, 0x026be}, // Soccer Ball ..Baseball
{0x026c4, 0x026c5}, // Snowman Without Snow ..Sun Behind Cloud
{0x026ce, 0x026ce}, // Ophiuchus ..Ophiuchus
{0x026d4, 0x026d4}, // No Entry ..No Entry
{0x026ea, 0x026ea}, // Church ..Church
{0x026f2, 0x026f3}, // Fountain ..Flag In Hole
{0x026f5, 0x026f5}, // Sailboat ..Sailboat
{0x026fa, 0x026fa}, // Tent ..Tent
{0x026fd, 0x026fd}, // Fuel Pump ..Fuel Pump
{0x02705, 0x02705}, // White Heavy Check Mark ..White Heavy Check Mark
{0x0270a, 0x0270b}, // Raised Fist ..Raised Hand
{0x02728, 0x02728}, // Sparkles ..Sparkles
{0x0274c, 0x0274c}, // Cross Mark ..Cross Mark
{0x0274e, 0x0274e}, // Negative Squared Cross M..Negative Squared Cross M
{0x02753, 0x02755}, // Black Question Mark Orna..White Exclamation Mark O
{0x02757, 0x02757}, // Heavy Exclamation Mark S..Heavy Exclamation Mark S
{0x02795, 0x02797}, // Heavy Plus Sign ..Heavy Division Sign
{0x027b0, 0x027b0}, // Curly Loop ..Curly Loop
{0x027bf, 0x027bf}, // Double Curly Loop ..Double Curly Loop
{0x02b1b, 0x02b1c}, // Black Large Square ..White Large Square
{0x02b50, 0x02b50}, // White Medium Star ..White Medium Star
{0x02b55, 0x02b55}, // Heavy Large Circle ..Heavy Large Circle
{0x02e80, 0x02e99}, // Cjk Radical Repeat ..Cjk Radical Rap
{0x02e9b, 0x02ef3}, // Cjk Radical Choke ..Cjk Radical C-simplified
{0x02f00, 0x02fd5}, // Kangxi Radical One ..Kangxi Radical Flute
{0x02ff0, 0x02ffb}, // Ideographic Description ..Ideographic Description
{0x03000, 0x0303e}, // Ideographic Space ..Ideographic Variation In
{0x03041, 0x03096}, // Hiragana Letter Small A ..Hiragana Letter Small Ke
{0x03099, 0x030ff}, // Combining Katakana-hirag..Katakana Digraph Koto
{0x03105, 0x0312f}, // Bopomofo Letter B ..Bopomofo Letter Nn
{0x03131, 0x0318e}, // Hangul Letter Kiyeok ..Hangul Letter Araeae
{0x03190, 0x031e3}, // Ideographic Annotation L..Cjk Stroke Q
{0x031f0, 0x0321e}, // Katakana Letter Small Ku..Parenthesized Korean Cha
{0x03220, 0x03247}, // Parenthesized Ideograph ..Circled Ideograph Koto
{0x03250, 0x04dbf}, // Partnership Sign ..(nil)
{0x04e00, 0x0a48c}, // Cjk Unified Ideograph-4e..Yi Syllable Yyr
{0x0a490, 0x0a4c6}, // Yi Radical Qot ..Yi Radical Ke
{0x0a960, 0x0a97c}, // Hangul Choseong Tikeut-m..Hangul Choseong Ssangyeo
{0x0ac00, 0x0d7a3}, // Hangul Syllable Ga ..Hangul Syllable Hih
{0x0f900, 0x0faff}, // Cjk Compatibility Ideogr..(nil)
{0x0fe10, 0x0fe19}, // Presentation Form For Ve..Presentation Form For Ve
{0x0fe30, 0x0fe52}, // Presentation Form For Ve..Small Full Stop
{0x0fe54, 0x0fe66}, // Small Semicolon ..Small Equals Sign
{0x0fe68, 0x0fe6b}, // Small Reverse Solidus ..Small Commercial At
{0x0ff01, 0x0ff60}, // Fullwidth Exclamation Ma..Fullwidth Right White Pa
{0x0ffe0, 0x0ffe6}, // Fullwidth Cent Sign ..Fullwidth Won Sign
{0x16fe0, 0x16fe4}, // Tangut Iteration Mark ..(nil)
{0x16ff0, 0x16ff1}, // (nil) ..(nil)
{0x17000, 0x187f7}, // (nil) ..(nil)
{0x18800, 0x18cd5}, // Tangut Component-001 ..(nil)
{0x18d00, 0x18d08}, // (nil) ..(nil)
{0x1b000, 0x1b11e}, // Katakana Letter Archaic ..Hentaigana Letter N-mu-m
{0x1b150, 0x1b152}, // Hiragana Letter Small Wi..Hiragana Letter Small Wo
{0x1b164, 0x1b167}, // Katakana Letter Small Wi..Katakana Letter Small N
{0x1b170, 0x1b2fb}, // Nushu Character-1b170 ..Nushu Character-1b2fb
{0x1f004, 0x1f004}, // Mahjong Tile Red Dragon ..Mahjong Tile Red Dragon
{0x1f0cf, 0x1f0cf}, // Playing Card Black Joker..Playing Card Black Joker
{0x1f18e, 0x1f18e}, // Negative Squared Ab ..Negative Squared Ab
{0x1f191, 0x1f19a}, // Squared Cl ..Squared Vs
{0x1f200, 0x1f202}, // Square Hiragana Hoka ..Squared Katakana Sa
{0x1f210, 0x1f23b}, // Squared Cjk Unified Ideo..Squared Cjk Unified Ideo
{0x1f240, 0x1f248}, // Tortoise Shell Bracketed..Tortoise Shell Bracketed
{0x1f250, 0x1f251}, // Circled Ideograph Advant..Circled Ideograph Accept
{0x1f260, 0x1f265}, // Rounded Symbol For Fu ..Rounded Symbol For Cai
{0x1f300, 0x1f320}, // Cyclone ..Shooting Star
{0x1f32d, 0x1f335}, // Hot Dog ..Cactus
{0x1f337, 0x1f37c}, // Tulip ..Baby Bottle
{0x1f37e, 0x1f393}, // Bottle With Popping Cork..Graduation Cap
{0x1f3a0, 0x1f3ca}, // Carousel Horse ..Swimmer
{0x1f3cf, 0x1f3d3}, // Cricket Bat And Ball ..Table Tennis Paddle And
{0x1f3e0, 0x1f3f0}, // House Building ..European Castle
{0x1f3f4, 0x1f3f4}, // Waving Black Flag ..Waving Black Flag
{0x1f3f8, 0x1f43e}, // Badminton Racquet And Sh..Paw Prints
{0x1f440, 0x1f440}, // Eyes ..Eyes
{0x1f442, 0x1f4fc}, // Ear ..Videocassette
{0x1f4ff, 0x1f53d}, // Prayer Beads ..Down-pointing Small Red
{0x1f54b, 0x1f54e}, // Kaaba ..Menorah With Nine Branch
{0x1f550, 0x1f567}, // Clock Face One Oclock ..Clock Face Twelve-thirty
{0x1f57a, 0x1f57a}, // Man Dancing ..Man Dancing
{0x1f595, 0x1f596}, // Reversed Hand With Middl..Raised Hand With Part Be
{0x1f5a4, 0x1f5a4}, // Black Heart ..Black Heart
{0x1f5fb, 0x1f64f}, // Mount Fuji ..Person With Folded Hands
{0x1f680, 0x1f6c5}, // Rocket ..Left Luggage
{0x1f6cc, 0x1f6cc}, // Sleeping Accommodation ..Sleeping Accommodation
{0x1f6d0, 0x1f6d2}, // Place Of Worship ..Shopping Trolley
{0x1f6d5, 0x1f6d7}, // Hindu Temple ..(nil)
{0x1f6eb, 0x1f6ec}, // Airplane Departure ..Airplane Arriving
{0x1f6f4, 0x1f6fc}, // Scooter ..(nil)
{0x1f7e0, 0x1f7eb}, // Large Orange Circle ..Large Brown Square
{0x1f90c, 0x1f93a}, // (nil) ..Fencer
{0x1f93c, 0x1f945}, // Wrestlers ..Goal Net
{0x1f947, 0x1f978}, // First Place Medal ..(nil)
{0x1f97a, 0x1f9cb}, // Face With Pleading Eyes ..(nil)
{0x1f9cd, 0x1f9ff}, // Standing Person ..Nazar Amulet
{0x1fa70, 0x1fa74}, // Ballet Shoes ..(nil)
{0x1fa78, 0x1fa7a}, // Drop Of Blood ..Stethoscope
{0x1fa80, 0x1fa86}, // Yo-yo ..(nil)
{0x1fa90, 0x1faa8}, // Ringed Planet ..(nil)
{0x1fab0, 0x1fab6}, // (nil) ..(nil)
{0x1fac0, 0x1fac2}, // (nil) ..(nil)
{0x1fad0, 0x1fad6}, // (nil) ..(nil)
{0x20000, 0x2fffd}, // Cjk Unified Ideograph-20..(nil)
{0x30000, 0x3fffd}, // (nil) ..(nil)
};
bool intable(struct width_interval* table, int table_length, int c) {
// First quick check for Latin1 etc. characters.
if (c < table[0].start) return false;
// Binary search in table.
int bot = 0;
int top = table_length - 1;
while (top >= bot) {
int mid = (bot + top) / 2;
if (table[mid].end < c) {
bot = mid + 1;
} else if (table[mid].start > c) {
top = mid - 1;
} else {
return true;
}
}
return false;
}
} // namespace
int wcwidth(wchar_t ucs) {
// NOTE: created by hand, there isn't anything identifiable other than
// general Cf category code to identify these, and some characters in Cf
// category code are of non-zero width.
if (ucs == 0 || ucs == 0x034F || (0x200B <= ucs && ucs <= 0x200F) ||
ucs == 0x2028 || ucs == 0x2029 || (0x202A <= ucs && ucs <= 0x202E) ||
(0x2060 <= ucs && ucs <= 0x2063)) {
return 0;
}
// C0/C1 control characters.
if (ucs < 32 || (0x07F <= ucs && ucs < 0x0A0)) return -1;
// Combining characters with zero width.
if (intable(ZERO_WIDTH, sizeof(ZERO_WIDTH) / sizeof(struct width_interval), ucs)) return 0;
return intable(WIDE_EASTASIAN, sizeof(WIDE_EASTASIAN) / sizeof(struct width_interval), ucs) ? 2 : 1;
}
int wcswidth(const wchar_t *wcs, size_t n) {
int ret = 0;
for(size_t i = 0; i < n && wcs[i]; i++) {
int cols = wcwidth(wcs[i]);
if (cols < 0)
return -1;
ret += cols;
}
return ret;
}
wchar_t *wcsdup(const wchar_t *s) {
size_t len = wcslen(s);
wchar_t *ret = (wchar_t *) malloc(sizeof(wchar_t) * (len + 1));
if(!ret)
return nullptr;
wmemcpy(ret, s, len + 1);
return ret;
}
int wcsncasecmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
for(size_t i = 0; i < n; i++) {
wint_t c1 = towlower(s1[i]);
wint_t c2 = towlower(s2[i]);
if(c1 == L'\0' && c2 == L'\0')
return 0;
if(c1 < c2)
return -1;
if(c1 > c2)
return 1;
}
return 0;
}
int wcscasecmp(const wchar_t *, const wchar_t *) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
size_t wcsnlen(const wchar_t *, size_t) {
__ensure(!"Not implemented");
__builtin_unreachable();
}
@@ -0,0 +1,9 @@
#include <wctype.h>
#include <bits/ensure.h>
#include <mlibc/debug.hpp>
#include <frg/string.hpp>
wctrans_t wctrans(const char *) { MLIBC_STUB_BODY; }
wint_t towctrans(wint_t, wctrans_t) { MLIBC_STUB_BODY; }