And implemented 128-bit muldiv on Windows.

This commit is contained in:
Pietro Gagliardi 2019-05-05 11:03:17 -04:00
parent 288c74b026
commit ff803bf792
5 changed files with 60 additions and 10 deletions

View File

@ -147,6 +147,12 @@ static void queueThread(void *data)
uiQueueMain(queued, p);
}
/*
TODO if I remove the uiQuit() from this test on Windows, I will occasionally get
=== RUN TestQueueMain_DifferentThread
../test/initmain.c:161: uiMain() timed out (5s)
--- FAIL: TestQueueMain_DifferentThread (4.9989539s)
*/
testingTest(QueueMain_DifferentThread)
{
threadThread *thread;

View File

@ -305,3 +305,48 @@ void timerprivMulDivUint64(uint64_t x, uint64_t y, uint64_t z, timerprivInt128 *
int128FromUint64(z, &c);
int128MulDiv64(&a, &b, &c, quot);
}
int64_t timerprivInt128ToInt64(const timerprivInt128 *n, int64_t min, int64_t max, int64_t minCap, int64_t maxCap)
{
if (n->neg) {
int64_t ret;
if (n->high > 0)
return minCap;
if (n->low > (uint64_t) INT64_MAX) {
// we can't safely convert n->low to int64_t
#if INT64_MIN == -INT64_MAX
// in this case, we can't store -n->low in an int64_t at all!
// therefore, it must be out of range
return minCap;
#else
// in this case, INT64_MIN == -INT64_MAX - 1
if (n->low > ((uint64_t) INT64_MAX) + 1)
// we still can't store -n->low in an int64_t
return minCap;
// only one option left
ret = INT64_MIN;
#endif
} else {
// -n->low can safely be stored in an int64_t, so do so
ret = (int64_t) (n->low);
ret = -ret;
}
if (ret < min)
return minCap;
return ret;
}
if (n->high > 0)
return maxCap;
if (n->low > (uint64_t) max)
return maxCap;
return (int64_t) (n->low);
}
uint64_t timerprivInt128ToUint64(const timerprivInt128 *n, uint64_t max, uint64_t maxCap)
{
if (n->neg)
return 0;
// TODO
return 0;
}

View File

@ -5,6 +5,7 @@
typedef int64_t timerDuration;
typedef int64_t timerTime;
#define timerTimeMin ((timerTime) INT64_MIN)
#define timerTimeMax ((timerTime) INT64_MAX)
#define timerNanosecond ((timerDuration) 1)

View File

@ -15,6 +15,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "timer.h"
#include "timerpriv.h"
static HRESULT lastErrorCodeToHRESULT(DWORD lastError)
{
@ -181,18 +182,13 @@ timerTime timerMonotonicNow(void)
timerDuration timerTimeSub(timerTime end, timerTime start)
{
LARGE_INTEGER qpf;
timerDuration qpnsQuot, qpnsRem;
timerTime c;
timerDuration ret;
timerprivInt128 quot;
QueryPerformanceFrequency(&qpf);
qpnsQuot = timerSecond / qpf.QuadPart;
qpnsRem = timerSecond % qpf.QuadPart;
c = end - start;
ret = ((timerDuration) c) * qpnsQuot;
ret += (c * qpnsRem) / qpf.QuadPart;
return ret;
timerprivMulDivInt64(end - start, timerSecond, qpf.QuadPart, &quot);
return timerprivInt128ToInt64(&quot,
INT64_MIN, INT64_MAX,
timerTimeMin, timerTimeMax);
}
// note: the idea for the SetThreadContext() nuttery is from https://www.codeproject.com/Articles/71529/Exception-Injection-Throwing-an-Exception-in-Other

View File

@ -10,3 +10,5 @@ struct timerprivInt128 {
extern void timerprivMulDivInt64(int64_t x, int64_t y, int64_t z, timerprivInt128 *quot);
extern void timerprivMulDivUint64(uint64_t x, uint64_t y, uint64_t z, timerprivInt128 *quot);
extern int64_t timerprivInt128ToInt64(const timerprivInt128 *n, int64_t min, int64_t max, int64_t minCap, int64_t maxCap);
extern uint64_t timerprivInt128ToUint64(const timerprivInt128 *n, uint64_t max, uint64_t maxCap);