Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/node_modules/@stdlib/math/base/special/acoth/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// MODULES //

var atanh = require( '@stdlib/math/base/special/atanh' );
var log1p = require( '@stdlib/math/base/special/log1p' );


// MAIN //
Expand Down Expand Up @@ -52,6 +53,13 @@ var atanh = require( '@stdlib/math/base/special/atanh' );
* // returns NaN
*/
function acoth( x ) {
// Near `|x| = 1`, `atanh( 1/x )` loses the low bits of `1-|1/x|` to the rounding of `1/x`. Use `acoth(x) = log( (x+1)/(x-1) )/2 = log1p( 2/(x-1) )/2` instead, where `x-1` is exact for `1 <= x <= 2`:
if ( x >= 1.0 && x <= 2.0 ) {
return 0.5 * log1p( 2.0 / ( x - 1.0 ) );
}
if ( x <= -1.0 && x >= -2.0 ) {
return -0.5 * log1p( 2.0 / ( -x - 1.0 ) );
}
return atanh( 1.0/x );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"libpath": [],
"dependencies": [
"@stdlib/math/base/napi/unary",
"@stdlib/math/base/special/atanh"
"@stdlib/math/base/special/atanh",
"@stdlib/math/base/special/log1p"
]
},
{
Expand All @@ -51,7 +52,8 @@
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/special/atanh"
"@stdlib/math/base/special/atanh",
"@stdlib/math/base/special/log1p"
]
},
{
Expand All @@ -65,7 +67,8 @@
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/special/atanh"
"@stdlib/math/base/special/atanh",
"@stdlib/math/base/special/log1p"
]
}
]
Expand Down
8 changes: 8 additions & 0 deletions lib/node_modules/@stdlib/math/base/special/acoth/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "stdlib/math/base/special/acoth.h"
#include "stdlib/math/base/special/atanh.h"
#include "stdlib/math/base/special/log1p.h"

/**
* Computes the inverse hyperbolic cotangent of a double-precision floating-point number.
Expand All @@ -30,5 +31,12 @@
* // returns ~0.5493
*/
double stdlib_base_acoth( const double x ) {
// Near `|x| = 1`, `atanh( 1/x )` loses the low bits of `1-|1/x|` to the rounding of `1/x`. Use `acoth(x) = log( (x+1)/(x-1) )/2 = log1p( 2/(x-1) )/2` instead, where `x-1` is exact for `1 <= x <= 2`:
if ( x >= 1.0 && x <= 2.0 ) {
return 0.5 * stdlib_base_log1p( 2.0 / ( x - 1.0 ) );
}
if ( x <= -1.0 && x >= -2.0 ) {
return -0.5 * stdlib_base_log1p( 2.0 / ( -x - 1.0 ) );
}
return stdlib_base_atanh( 1.0 / x );
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import JSON

"""
gen( domain, name )

Check failure on line 22 in lib/node_modules/@stdlib/math/base/special/acoth/test/fixtures/julia/runner.jl

View workflow job for this annotation

GitHub Actions / Lint Changed Files

wrong indentation type (spaces instead of tabs)

Generate fixture data and write to file.

Expand All @@ -37,7 +37,9 @@
"""
function gen( domain, name )
x = collect( domain );
y = acoth.( x );
y = setprecision( BigFloat, 256 ) do
Float64.( acoth.( BigFloat.( x ) ) );
end

# Store data to be written to file as a collection:
data = Dict([
Expand Down Expand Up @@ -92,3 +94,11 @@
# Huge negative values:
x = range( -1.0e300, stop = -1.0e308, length = 1003 );
gen( x, "huge_negative.json" );

# Values close to one (in `Float64`, `acoth` is `atanh(1/x)` and loses the low bits of `1-1/x`):
x = 1.0 .+ exp10.( range( -15.0, stop = -1.0, length = 1000 ) );
gen( x, "near_positive_one.json" );

x = -1.0 .- exp10.( range( -15.0, stop = -1.0, length = 1000 ) );
gen( x, "near_negative_one.json" );

40 changes: 36 additions & 4 deletions lib/node_modules/@stdlib/math/base/special/acoth/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ var largerNegative = require( './fixtures/julia/larger_negative.json' );
var largeNegative = require( './fixtures/julia/large_negative.json' );
var mediumNegative = require( './fixtures/julia/medium_negative.json' );
var hugeNegative = require( './fixtures/julia/huge_negative.json' );
var nearPositiveOne = require( './fixtures/julia/near_positive_one.json' );
var nearNegativeOne = require( './fixtures/julia/near_negative_one.json' );


// TESTS //
Expand All @@ -57,7 +59,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for medium positiv
expected = mediumPositive.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -72,7 +74,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for medium negativ
expected = mediumNegative.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -87,7 +89,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for large positive
expected = largePositive.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -102,7 +104,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for large negative
expected = largeNegative.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand Down Expand Up @@ -167,6 +169,36 @@ tape( 'the function computes the inverse hyperbolic cotangent for huge negative
t.end();
});

tape( 'the function computes the inverse hyperbolic cotangent for values close to `1`', function test( t ) {
var expected;
var x;
var y;
var i;

x = nearPositiveOne.x;
expected = nearPositiveOne.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the function computes the inverse hyperbolic cotangent for values close to `-1`', function test( t ) {
var expected;
var x;
var y;
var i;

x = nearNegativeOne.x;
expected = nearNegativeOne.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the function returns `NaN` if provided `NaN`', function test( t ) {
var v = acoth( NaN );
t.strictEqual( isnan( v ), true, 'returns expected value' );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ var largerNegative = require( './fixtures/julia/larger_negative.json' );
var largeNegative = require( './fixtures/julia/large_negative.json' );
var mediumNegative = require( './fixtures/julia/medium_negative.json' );
var hugeNegative = require( './fixtures/julia/huge_negative.json' );
var nearPositiveOne = require( './fixtures/julia/near_positive_one.json' );
var nearNegativeOne = require( './fixtures/julia/near_negative_one.json' );


// VARIABLES //
Expand Down Expand Up @@ -66,7 +68,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for medium positiv
expected = mediumPositive.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -81,7 +83,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for medium negativ
expected = mediumNegative.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -96,7 +98,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for large positive
expected = largePositive.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand All @@ -111,7 +113,7 @@ tape( 'the function computes the inverse hyperbolic cotangent for large negative
expected = largeNegative.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 2 ), true, 'returns expected value' );
}
t.end();
});
Expand Down Expand Up @@ -176,6 +178,36 @@ tape( 'the function computes the inverse hyperbolic cotangent for huge negative
t.end();
});

tape( 'the function computes the inverse hyperbolic cotangent for values close to `1`', opts, function test( t ) {
var expected;
var x;
var y;
var i;

x = nearPositiveOne.x;
expected = nearPositiveOne.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the function computes the inverse hyperbolic cotangent for values close to `-1`', opts, function test( t ) {
var expected;
var x;
var y;
var i;

x = nearNegativeOne.x;
expected = nearNegativeOne.expected;
for ( i = 0; i < x.length; i++ ) {
y = acoth( x[ i ] );
t.strictEqual( isAlmostSameValue( y, expected[ i ], 1 ), true, 'returns expected value' );
}
t.end();
});

tape( 'the function returns `NaN` if provided `NaN`', opts, function test( t ) {
var v = acoth( NaN );
t.strictEqual( isnan( v ), true, 'returns expected value' );
Expand Down
Loading