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
84 changes: 82 additions & 2 deletions regression/cbmc-library/cos-01/main.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,89 @@
#define _USE_MATH_DEFINES
#include <assert.h>
#include <math.h>

int main()
{
cos();
assert(0);
// Test special values - these should be precise
double c;

// cos(0) should be exactly 1
c = cos(0.0);
assert(c >= 0.999999999 && c <= 1.0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compare with 1, as suggested in the comment.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.999999999 == 0x1.fffffff768fa1p-1

so this allows around 22 bits difference so only a bit more accurate than float. I would recommend a tighter bound.


// cos(π/2) should be approximately 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can work it out exactly. If we use a correctly rounded implementation such as https://core-math.gitlabpages.inria.fr/ then we can compute the double nearest to cos(M_PI / 2.0). Note that it is small but it is not zero. In fact, IIRC, it is a lot further away from zero than you might think because M_PI != \pi.

Personally I would try computing each of these using something like CORE-MATH and then adding an error in the range of a few ULP. Happy to give this a go if useful.

c = cos(M_PI / 2.0);
assert(c >= -1e-10 && c <= 1e-10);

// cos(-π/2) should be approximately 0
c = cos(-M_PI / 2.0);
assert(c >= -1e-10 && c <= 1e-10);

// cos(π) should be approximately -1
c = cos(M_PI);
assert(c >= -1.0 && c <= -0.999999999);

// cos(-π) should be approximately -1 (cos is even)
c = cos(-M_PI);
assert(c >= -1.0 && c <= -0.999999999);

// cos(2π) should be approximately 1
c = cos(2.0 * M_PI);
assert(c >= 0.999999999 && c <= 1.0);

// Test range narrowing for [-π/2, π/2]
c = cos(M_PI / 4.0); // 45 degrees
assert(c >= 0.0 && c <= 1.0); // Should be in [0, 1]
Copy link
Collaborator

@martin-cs martin-cs Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike sin, which can produce very small outputs (but only in [-\pi/2, \pi/2], cos has quite a high lower bound on it's outputs. Off the top of my head I think it is something like 0x1.0p-100, very small but a tiny part of the range of double.


// Test range narrowing for [π/2, 3π/2]
c = cos(M_PI); // 180 degrees
assert(c >= -1.0 && c <= 0.0); // Should be in [-1, 0]

// Test range narrowing for [3π/2, 2π]
c = cos(7.0 * M_PI / 4.0); // 315 degrees
assert(c >= 0.0 && c <= 1.0); // Should be in [0, 1]

// ========== COSINE TESTS ==========

// Test 7: cos(0) ≈ 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These just repeat the above.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a duplicate of line 10.

{
double c = cos(0.0);
assert(c >= 0.99 && c <= 1.0);
}

// Test 8: cos(π/2) ≈ 0
{
double c = cos(M_PI / 2.0);
assert(c >= -1e-9 && c <= 1e-9);
}

// Test 9: cos(π) ≈ -1
{
double c = cos(M_PI);
assert(c >= -1.0 && c <= -0.99);
}

// Test 10: cos(2π) ≈ 1
{
double c = cos(2.0 * M_PI);
assert(c >= 0.99 && c <= 1.0);
}

// Test 11: Range narrowing - cos(x) ≥ 0 for x in [-π/2, π/2]
{
double x;
__CPROVER_assume(x >= -M_PI / 2.0 + 0.1 && x <= M_PI / 2.0 - 0.1);
double c = cos(x);
assert(c >= 0.0 && c <= 1.0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, these can be tightened quite a bit.

}

// Test 12: Range narrowing - cos(x) ≤ 0 for x in [π/2, 3π/2]
{
double x;
__CPROVER_assume(x >= M_PI / 2.0 + 0.1 && x <= 3.0 * M_PI / 2.0 - 0.1);
double c = cos(x);
assert(c >= -1.0 && c <= 0.0);
}

return 0;
}
6 changes: 3 additions & 3 deletions regression/cbmc-library/cos-01/test.desc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
KNOWNBUG
CORE
main.c
--pointer-check --bounds-check
--floatbv
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
^warning: ignoring
^warning: ignoring
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spurious newline change

25 changes: 25 additions & 0 deletions regression/cbmc-library/cos-02/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#define _USE_MATH_DEFINES
#include <assert.h>
#include <math.h>

int main()
{
// ========== COMBINED TESTS ==========

// Test 15: Pythagorean identity approximation for x = π/4
{
double x = M_PI / 4.0;
double s = sin(x);
double c = cos(x);

// Both should be positive for this quadrant
assert(s >= 0.0 && s <= 1.0);
assert(c >= 0.0 && c <= 1.0);

// And both should be close to √2/2 ≈ 0.707
assert(s >= 0.6 && s <= 0.8);
assert(c >= 0.6 && c <= 0.8);
}

return 0;
}
8 changes: 8 additions & 0 deletions regression/cbmc-library/cos-02/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.c
--floatbv
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
^warning: ignoring
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spurious newline change

23 changes: 20 additions & 3 deletions regression/cbmc-library/cosf-01/main.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
#define _USE_MATH_DEFINES
#include <assert.h>
#include <math.h>

int main()
{
cosf();
assert(0);
return 0;
// ========== FLOAT TESTS ==========

// Test 13: sinf with special values
{
float s0 = sinf(0.0f);
float s_pi_half = sinf(3.14159265f / 2.0f);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File is called cosf, but tests sinf.


assert(s0 >= -1e-4f && s0 <= 1e-4f);
assert(s_pi_half >= 0.999f && s_pi_half <= 1.0f);
}

// Test 14: cosf with special values
{
float c0 = cosf(0.0f);
float c_pi = cosf(3.14159265f);

assert(c0 >= 0.999f && c0 <= 1.0f);
assert(c_pi >= -1.0f && c_pi <= -0.999f);
}
}
6 changes: 3 additions & 3 deletions regression/cbmc-library/cosf-01/test.desc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
KNOWNBUG
CORE
main.c
--pointer-check --bounds-check
--floatbv
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
^warning: ignoring
^warning: ignoring
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spurious newline change

92 changes: 84 additions & 8 deletions regression/cbmc-library/sin-01/main.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,93 @@
#define _USE_MATH_DEFINES
#include <assert.h>
#include <math.h>

int main()
{
double s, f = 0.0, fStep = 0.1 * M_PI;
int n = 0;
// Test special values - these should be precise
double s;

do
// sin(0) should be exactly 0
s = sin(0.0);
assert(s >= -1e-10 && s <= 1e-10);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above


// sin(π/2) should be approximately 1
s = sin(M_PI / 2.0);
assert(s >= 0.999999999 && s <= 1.0);

// sin(-π/2) should be approximately -1
s = sin(-M_PI / 2.0);
assert(s >= -1.0 && s <= -0.999999999);

// sin(π) should be approximately 0
s = sin(M_PI);
assert(s >= -1e-10 && s <= 1e-10);

// sin(-π) should be approximately 0
s = sin(-M_PI);
assert(s >= -1e-10 && s <= 1e-10);

// sin(2π) should be approximately 0
s = sin(2.0 * M_PI);
assert(s >= -1e-10 && s <= 1e-10);

// Test range narrowing for first quadrant [0, π/2]
s = sin(M_PI / 4.0); // 45 degrees
assert(s >= 0.0 && s <= 1.0); // Should be in [0, 1]

// Test range narrowing for second quadrant [π/2, π]
s = sin(3.0 * M_PI / 4.0); // 135 degrees
assert(s >= 0.0 && s <= 1.0); // Should be in [0, 1]

// Test range narrowing for third quadrant [π, 3π/2]
s = sin(5.0 * M_PI / 4.0); // 225 degrees
assert(s >= -1.0 && s <= 0.0); // Should be in [-1, 0]

// Test range narrowing for fourth quadrant [3π/2, 2π]
s = sin(7.0 * M_PI / 4.0); // 315 degrees
assert(s >= -1.0 && s <= 0.0); // Should be in [-1, 0]

// ========== SINE TESTS ==========

// Test 1: sin(0) ≈ 0
{
double s = sin(0.0);
assert(s >= -1e-9 && s <= 1e-9);
}

// Test 2: sin(π/2) ≈ 1
{
double s = sin(M_PI / 2.0);
assert(s >= 0.99 && s <= 1.0);
}

// Test 3: sin(-π/2) ≈ -1
{
double s = sin(-M_PI / 2.0);
assert(s >= -1.0 && s <= -0.99);
}

// Test 4: sin(π) ≈ 0
{
double s = sin(M_PI);
assert(s >= -1e-9 && s <= 1e-9);
}

// Test 5: Range narrowing - sin(x) ≥ 0 for x in [0, π]
{
double x;
__CPROVER_assume(x >= 0.1 && x <= M_PI - 0.1);
double s = sin(x);
assert(s >= 0.0 && s <= 1.0);
}

// Test 6: Range narrowing - sin(x) ≤ 0 for x in [π, 2π]
{
s = sin(f);
f += fStep;
n++;
} while(f < M_PI);
double x;
__CPROVER_assume(x >= M_PI + 0.1 && x <= 2.0 * M_PI - 0.1);
double s = sin(x);
assert(s >= -1.0 && s <= 0.0);
}

assert(n < 11);
return 0;
}
33 changes: 30 additions & 3 deletions regression/cbmc-library/sinf-01/main.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,36 @@
#define _USE_MATH_DEFINES
#include <assert.h>
#include <math.h>

int main()
{
sinf();
assert(0);
// Test special values with float precision
float s;
const float pi = 3.14159265f;

// sin(0) should be exactly 0
s = sinf(0.0f);
assert(s >= -1e-5f && s <= 1e-5f);

// sin(π/2) should be approximately 1
s = sinf(pi / 2.0f);
assert(s >= 0.99999f && s <= 1.0f);

// sin(-π/2) should be approximately -1
s = sinf(-pi / 2.0f);
assert(s >= -1.0f && s <= -0.99999f);

// sin(π) should be approximately 0
s = sinf(pi);
assert(s >= -1e-5f && s <= 1e-5f);

// Test range narrowing for [0, π]
s = sinf(pi / 4.0f);
assert(s >= 0.0f && s <= 1.0f);

// Test range narrowing for [π, 2π]
s = sinf(5.0f * pi / 4.0f);
assert(s >= -1.0f && s <= 0.0f);

return 0;
}
}
6 changes: 3 additions & 3 deletions regression/cbmc-library/sinf-01/test.desc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
KNOWNBUG
CORE
main.c
--pointer-check --bounds-check
--floatbv
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
^warning: ignoring
^warning: ignoring
Loading
Loading