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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ Returns the result of adding two timespec structures.

Returns the result of subtracting ts2 from ts1.

`struct timespec timespec_idiv(struct timespec ts, long divisor)`

Returns the result of dividing ts by divisor

`struct timespec timespec_mod(struct timespec ts1, struct timespec ts2)`

Returns the remainder left over after dividing ts1 by ts2.
Expand Down
54 changes: 53 additions & 1 deletion timespec.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,33 @@ struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
return timespec_normalise(ts1);
}

/** \fn struct timespec timespec_idiv(struct timespec ts, long divisor)
* \brief Returns the result of dividing a timespec structure by a long number.
*/
struct timespec timespec_idiv(struct timespec ts, long divisor)
{
struct timespec result = {0, 0};

// Prevent division by zero
if (divisor == 0)
return result;

/* Normalise inputs to prevent tv_nsec rollover if whole-second values
* are packed in it.
*/
ts = timespec_normalise(ts);

// First divide seconds to prevent overflow
result.tv_sec = ts.tv_sec / divisor;

// Handle the remainder from seconds division plus the original nanoseconds
unsigned long rem_sec = ts.tv_sec % divisor;
unsigned long extra_nsec = rem_sec * NSEC_PER_SEC;
result.tv_nsec = (ts.tv_nsec + extra_nsec) / divisor;

return result;
}

/** \fn struct timespec timespec_mod(struct timespec ts1, struct timespec ts2)
* \brief Returns the remainder left over after dividing ts1 by ts2 (ts1%ts2).
*/
Expand Down Expand Up @@ -473,6 +500,19 @@ struct timespec timespec_normalise(struct timespec ts)
} \
}

#define TEST_DIV_FUNC(ts_sec, ts_nsec, divisor, expect_sec, expect_nsec) { \
struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \
struct timespec got = timespec_idiv(ts, divisor); \
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
{ \
printf("%s:%d: timespec_idiv ({%ld, %ld}, %ld) returned wrong value\n", __FILE__, __LINE__, \
(long)(ts_sec), (long)(ts_nsec), (long)(divisor)); \
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
++result; \
} \
}

#define TEST_FROM_DOUBLE(d_secs, expect_sec, expect_nsec) { \
struct timespec got = timespec_from_double(d_secs); \
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
Expand Down Expand Up @@ -603,7 +643,19 @@ int main()
TEST_BINOP(timespec_mod, 12345,54321, 0,100001, 0,5555);
TEST_BINOP(timespec_mod, LONG_MAX,0, 0,1, 0,0);
TEST_BINOP(timespec_mod, LONG_MAX,0, LONG_MAX,1, LONG_MAX,0);


//timespec_idiv
TEST_DIV_FUNC(1,500000000, 0, 0,0);
TEST_DIV_FUNC(10,0, 2, 5,0);
TEST_DIV_FUNC(7,0, 2, 3,500000000);
TEST_DIV_FUNC(5,500000000, 5, 1,100000000);
TEST_DIV_FUNC(0,0, 3, 0,0);
TEST_DIV_FUNC(10,500000000, 3, 3,500000000);
TEST_DIV_FUNC(10,0, 3, 3,333333333);
TEST_DIV_FUNC(1040,200000000, 7, 148,600000000);
TEST_DIV_FUNC(222,222222222, 2, 111,111111111);
TEST_DIV_FUNC(0,125, 25, 0,5);

// timespec_clamp

TEST_TRINOP(timespec_clamp, 0,0, 0,0, 0,0, 0,0);
Expand Down
1 change: 1 addition & 0 deletions timespec.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extern "C" {

struct timespec timespec_add(struct timespec ts1, struct timespec ts2);
struct timespec timespec_sub(struct timespec ts1, struct timespec ts2);
struct timespec timespec_idiv(struct timespec ts, long divisor);
struct timespec timespec_mod(struct timespec ts1, struct timespec ts2);

struct timespec timespec_min(struct timespec ts1, struct timespec ts2);
Expand Down