Skip to content
Open
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
21 changes: 19 additions & 2 deletions lib/node_modules/@stdlib/math/base/special/haversin/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,31 @@

// MODULES //

var cos = require( '@stdlib/math/base/special/cos' );
var abs2 = require( '@stdlib/math/base/special/abs2' );
var sin = require( '@stdlib/math/base/special/sin' );


// MAIN //

/**
* Computes the half-value versed sine.
*
* ## Method
*
* Evaluating the textbook formula
*
* ```tex
* \operatorname{haversin}(x) = \frac{1 - \cos(x)}{2}
* ```
*
* loses significant digits when \\(\cos(x)\\) is close to one (i.e., for `x` near multiples of 2π, including small `x`). Accordingly, we use the equivalent half-angle identity
*
* ```tex
* \operatorname{haversin}(x) = \sin^2\left(\tfrac{x}{2}\right)
* ```
*
* which does not suffer from cancellation.
*
* @param {number} x - input value (in radians)
* @returns {number} half-value versed sine
*
Expand All @@ -48,7 +65,7 @@ var cos = require( '@stdlib/math/base/special/cos' );
* // returns NaN
*/
function haversin( x ) {
return (1.0 - cos( x )) / 2.0;
return abs2( sin( x / 2.0 ) );
}


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/cos"
"@stdlib/math/base/special/abs2",
"@stdlib/math/base/special/sin"
]
},
{
Expand All @@ -51,7 +52,8 @@
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/special/cos"
"@stdlib/math/base/special/abs2",
"@stdlib/math/base/special/sin"
]
},
{
Expand All @@ -65,7 +67,8 @@
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/special/cos"
"@stdlib/math/base/special/abs2",
"@stdlib/math/base/special/sin"
]
}
]
Expand Down
21 changes: 19 additions & 2 deletions lib/node_modules/@stdlib/math/base/special/haversin/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,28 @@
*/

#include "stdlib/math/base/special/haversin.h"
#include "stdlib/math/base/special/cos.h"
#include "stdlib/math/base/special/abs2.h"
#include "stdlib/math/base/special/sin.h"

/**
* Computes the half-value versed sine.
*
* ## Method
*
* Evaluating the textbook formula
*
* ```tex
* \operatorname{haversin}(x) = \frac{1 - \cos(x)}{2}
* ```
*
* loses significant digits when `cos(x)` is close to one (i.e., for `x` near multiples of 2π, including small `x`). Accordingly, we use the equivalent half-angle identity
*
* ```tex
* \operatorname{haversin}(x) = \sin^2\left(\tfrac{x}{2}\right)
* ```
*
* which does not suffer from cancellation.
*
* @param x input value (in radians)
* @return half-value versed sine
*
Expand All @@ -30,5 +47,5 @@
* // returns 0.0
*/
double stdlib_base_haversin( const double x ) {
return ( 1.0 - stdlib_base_cos( x ) ) / 2.0;
return stdlib_base_abs2( stdlib_base_sin( x / 2.0 ) );
}

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, filepath )
gen( domain, filepath )

Generate fixture data and write to file.

Expand All @@ -37,7 +37,12 @@ julia> gen( x, \"./data.json\" );
"""
function gen( domain, filepath )
x = collect( domain );
y = (1.0 .- cos.( x )) ./ 2.0;

# Evaluate the textbook formula in extended precision (4096 bits resolve the cancellation even for the smallest `x`), and round the result to double precision:
y = setprecision( BigFloat, 4096 ) do
Float64.( ( 1 .- cos.( big.( x ) ) ) ./ 2 )
end

data = Dict([
("x", x),
("expected", y)
Expand All @@ -54,6 +59,16 @@ file = @__FILE__;
# Extract the directory in which this file resides:
dir = dirname( file );

# Negative small values:
x = -exp10.( range( -300.0, stop = 0.0, length = 4000 ) )
out = joinpath( dir, "small_negative.json" );
gen( x, out );

# Positive small values:
x = exp10.( range( -300.0, stop = 0.0, length = 4000 ) )
out = joinpath( dir, "small_positive.json" );
gen( x, out );

# Negative medium sized values:
x = range( -256.0*pi, stop = 0.0, length = 4000 )
out = joinpath( dir, "medium_negative.json" );
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

49 changes: 43 additions & 6 deletions lib/node_modules/@stdlib/math/base/special/haversin/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// MODULES //

var tape = require( 'tape' );
var isAlmostSameValue = require( '@stdlib/assert/is-almost-same-value' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var PINF = require( '@stdlib/constants/float64/pinf' );
var NINF = require( '@stdlib/constants/float64/ninf' );
Expand All @@ -29,6 +30,8 @@ var haversin = require( './../lib' );

// FIXTURES //

var smallNegative = require( './fixtures/julia/small_negative.json' );
var smallPositive = require( './fixtures/julia/small_positive.json' );
var mediumNegative = require( './fixtures/julia/medium_negative.json' );
var mediumPositive = require( './fixtures/julia/medium_positive.json' );
var largeNegative = require( './fixtures/julia/large_negative.json' );
Expand All @@ -45,6 +48,40 @@ tape( 'main export is a function', function test( t ) {
t.end();
});

tape( 'the function computes the half-value versed sine (for -1 <= x <= -1e-300)', function test( t ) {
var expected;
var x;
var y;
var i;

x = smallNegative.x;
expected = smallNegative.expected;

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

t.end();
});

tape( 'the function computes the half-value versed sine (for 1e-300 <= x <= 1)', function test( t ) {
var expected;
var x;
var y;
var i;

x = smallPositive.x;
expected = smallPositive.expected;

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

t.end();
});

tape( 'the function computes the half-value versed sine (for -256*pi < x < 0 )', function test( t ) {
var expected;
var x;
Expand All @@ -56,7 +93,7 @@ tape( 'the function computes the half-value versed sine (for -256*pi < x < 0 )',

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

t.end();
Expand All @@ -73,7 +110,7 @@ tape( 'the function computes the half-value versed sine (for 0 < x < 256*pi )',

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

t.end();
Expand All @@ -90,7 +127,7 @@ tape( 'the function computes the half-value versed sine (for -2**60 (pi/2) < x <

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

t.end();
Expand All @@ -107,7 +144,7 @@ tape( 'the function computes the half-value versed sine (for 2**20 (pi/2) < x <

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

t.end();
Expand All @@ -124,7 +161,7 @@ tape( 'the function computes the half-value versed sine (for x <= -2**60 (PI/2)

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

t.end();
Expand All @@ -141,7 +178,7 @@ tape( 'the function computes the half-value versed sine (for x >= 2**60 (PI/2) )

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

t.end();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ var opts = {

// FIXTURES //

var smallNegative = require( './fixtures/julia/small_negative.json' );
var smallPositive = require( './fixtures/julia/small_positive.json' );
var mediumNegative = require( './fixtures/julia/medium_negative.json' );
var mediumPositive = require( './fixtures/julia/medium_positive.json' );
var largeNegative = require( './fixtures/julia/large_negative.json' );
Expand All @@ -55,6 +57,40 @@ tape( 'main export is a function', opts, function test( t ) {
t.end();
});

tape( 'the function computes the half-value versed sine (for -1 <= x <= -1e-300)', opts, function test( t ) {
var expected;
var x;
var y;
var i;

x = smallNegative.x;
expected = smallNegative.expected;

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

t.end();
});

tape( 'the function computes the half-value versed sine (for 1e-300 <= x <= 1)', opts, function test( t ) {
var expected;
var x;
var y;
var i;

x = smallPositive.x;
expected = smallPositive.expected;

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

t.end();
});

tape( 'the function computes the half-value versed sine (for -256*pi < x < 0 )', opts, function test( t ) {
var expected;
var x;
Expand Down
21 changes: 19 additions & 2 deletions lib/node_modules/@stdlib/math/base/special/versin/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,31 @@

// MODULES //

var cos = require( '@stdlib/math/base/special/cos' );
var abs2 = require( '@stdlib/math/base/special/abs2' );
var sin = require( '@stdlib/math/base/special/sin' );


// MAIN //

/**
* Computes the versed sine.
*
* ## Method
*
* Evaluating the textbook formula
*
* ```tex
* \operatorname{versin}(x) = 1 - \cos(x)
* ```
*
* loses significant digits when \\(\cos(x)\\) is close to one (i.e., for `x` near multiples of 2π, including small `x`). Accordingly, we use the equivalent half-angle identity
*
* ```tex
* \operatorname{versin}(x) = 2 \sin^2\left(\tfrac{x}{2}\right)
* ```
*
* which does not suffer from cancellation.
*
* @param {number} x - input value (in radians)
* @returns {number} versed sine
*
Expand All @@ -48,7 +65,7 @@ var cos = require( '@stdlib/math/base/special/cos' );
* // returns NaN
*/
function versin( x ) {
return 1.0 - cos( x );
return 2.0 * abs2( sin( x / 2.0 ) );
}


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/cos"
"@stdlib/math/base/special/abs2",
"@stdlib/math/base/special/sin"
]
},
{
Expand All @@ -51,7 +52,8 @@
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/special/cos"
"@stdlib/math/base/special/abs2",
"@stdlib/math/base/special/sin"
]
},
{
Expand All @@ -65,7 +67,8 @@
"libraries": [],
"libpath": [],
"dependencies": [
"@stdlib/math/base/special/cos"
"@stdlib/math/base/special/abs2",
"@stdlib/math/base/special/sin"
]
}
]
Expand Down
Loading
Loading