185#if defined(__APPLE__)
187 size_t logical_size =
sizeof(logical);
188 if (sysctlbyname(
"hw.logicalcpu", &logical, &logical_size,
nullptr, 0) != 0)
192 size_t physical_size =
sizeof(physical);
193 if (sysctlbyname(
"hw.physicalcpu", &physical, &physical_size,
nullptr, 0) != 0)
196 return std::make_pair(logical, physical);
197#elif defined(unix) || defined(__unix) || defined(__unix__)
198 static std::regex pattern(
"core id(.*): (.*)");
203 std::ifstream stream(
"/proc/cpuinfo");
204 while (getline(stream, line))
207 if (std::regex_match(line, matches, pattern))
208 cores.insert(atoi(matches[2].str().c_str()));
211 size_t logical = cores.size();
212 long physical = sysconf(_SC_NPROCESSORS_ONLN);
213 return std::make_pair(logical, physical);
214#elif defined(_WIN32) || defined(_WIN64)
215 BOOL allocated = FALSE;
216 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pBuffer =
nullptr;
221 BOOL bResult = GetLogicalProcessorInformation(pBuffer, &dwLength);
222 if (bResult == FALSE)
224 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
226 if (pBuffer !=
nullptr)
228 pBuffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)std::malloc(dwLength);
229 if (pBuffer ==
nullptr)
230 return std::make_pair(-1, -1);
233 return std::make_pair(-1, -1);
239 std::pair<int, int> result(0, 0);
240 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pCurrent = pBuffer;
243 while (dwOffset +
sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= dwLength)
245 switch (pCurrent->Relationship)
247 case RelationProcessorCore:
248 result.first += Internals::CountSetBits(pCurrent->ProcessorMask);
251 case RelationNumaNode:
253 case RelationProcessorPackage:
256 return std::make_pair(-1, -1);
258 dwOffset +=
sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
266 #error Unsupported platform
272#if defined(__APPLE__)
273 uint64_t frequency = 0;
274 size_t frequency_size =
sizeof(frequency);
275 if (sysctlbyname(
"hw.cpufrequency", &frequency, &frequency_size,
nullptr, 0) == 0)
279 struct clockinfo clockrate;
280 size_t clockrate_size =
sizeof(clockrate);
281 if ((sysctlbyname(
"hw.tbfrequency", &frequency, &frequency_size, NULL, 0) == 0) && (sysctlbyname(
"kern.clockrate", &clockrate, &clockrate_size, NULL, 0) == 0))
282 return frequency * clockrate.hz;
285#elif defined(unix) || defined(__unix) || defined(__unix__)
286 static std::regex pattern(
"cpu MHz(.*): (.*)");
289 std::ifstream stream(
"/proc/cpuinfo");
290 while (getline(stream, line))
293 if (std::regex_match(line, matches, pattern))
294 return (int64_t)(atof(matches[2].str().c_str()) * 1000000);
298#elif defined(_WIN32) || defined(_WIN64)
300 long lError = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKeyProcessor);
301 if (lError != ERROR_SUCCESS)
305 auto clearer = [](HKEY hKey) { RegCloseKey(hKey); };
306 auto key = std::unique_ptr<std::remove_pointer<HKEY>::type,
decltype(clearer)>(hKeyProcessor, clearer);
309 DWORD dwBufferSize =
sizeof(DWORD);
310 lError = RegQueryValueExA(key.get(),
"~MHz",
nullptr,
nullptr, (LPBYTE)&dwMHz, &dwBufferSize);
311 if (lError != ERROR_SUCCESS)
314 return dwMHz * 1000000;
316 #error Unsupported platform
401#if defined(__APPLE__)
402 static mach_timebase_info_data_t info;
403 static uint64_t bias = Internals::PrepareTimebaseInfo(info);
404 return ((mach_absolute_time() - bias) * info.numer) / info.denom;
405#elif defined(unix) || defined(__unix) || defined(__unix__)
406 struct timespec timestamp = { 0 };
407 clock_gettime(CLOCK_MONOTONIC, ×tamp);
408 return (timestamp.tv_sec * 1000000000) + timestamp.tv_nsec;
409#elif defined(_WIN32) || defined(_WIN64)
410 static uint64_t offset = 0;
411 static LARGE_INTEGER first = { 0 };
412 static LARGE_INTEGER frequency = { 0 };
413 static bool initialized =
false;
414 static bool qpc =
true;
420 GetSystemTimePreciseAsFileTime(×tamp);
422 ULARGE_INTEGER result;
423 result.LowPart = timestamp.dwLowDateTime;
424 result.HighPart = timestamp.dwHighDateTime;
427 result.QuadPart -= 116444736000000000ll;
428 offset = result.QuadPart * 100;
431 qpc = QueryPerformanceFrequency(&frequency) && QueryPerformanceCounter(&first);
438 LARGE_INTEGER timestamp = { 0 };
439 QueryPerformanceCounter(×tamp);
440 timestamp.QuadPart -= first.QuadPart;
441 return offset +
MulDiv64(timestamp.QuadPart, 1000000000, frequency.QuadPart);
446 #error Unsupported platform
452#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
453 __uint128_t a = operant;
454 __uint128_t b = multiplier;
455 __uint128_t c = divider;
457 return (uint64_t)(a * b / c);
458#elif defined(_MSC_VER)
467 #define REMAINDER quotient
473 mov eax, dword ptr[operant+4]
474 xor eax, dword ptr[multiplier+4]
475 xor eax, dword ptr[divider+4]
482 mov eax, dword ptr[divider+4]
483 or eax, dword ptr[divider]
490 cmp eax, dword ptr[multiplier+4]
492 cmp eax, dword ptr[multiplier]
500 mov dword ptr[edi+12], eax
501 mov dword ptr[edi+8], eax
503 cmp eax, dword ptr[multiplier]
506 mov eax, dword ptr[operant+4]
507 mov dword ptr[edi+4], eax
508 mov eax, dword ptr[operant]
509 mov dword ptr[edi], eax
514 mov ecx, dword ptr[operant+4]
515 or ecx, eax ;test
for both hiwords zero.
518 mov ecx, dword ptr[multiplier]
519 mov eax, dword ptr[operant]
521 mov dword ptr[edi+4], edx
522 mov dword ptr[edi], eax
527 mov eax, dword ptr[multiplier]
528 mul dword ptr[operant]
529 mov dword ptr[edi], eax
532 mov eax, dword ptr[multiplier]
533 mul dword ptr[operant+4]
539 mov eax, dword ptr[multiplier+4]
540 mul dword ptr[operant]
542 mov dword ptr[edi+4], eax
546 mov eax, dword ptr[multiplier+4]
547 mul dword ptr[operant+4]
551 mov dword ptr[edi+8], eax
552 mov dword ptr[edi+12], edx
557 mov eax, dword ptr[divider+4]
560 mov ecx, dword ptr[divider]
565 mov eax, dword ptr[edi+12]
568 mov dword ptr[quotient+12], eax
570 mov eax, dword ptr[edi+8]
572 mov dword ptr[quotient+8], eax
574 mov eax, dword ptr[edi+4]
576 mov dword ptr[quotient+4], eax
578 mov eax, dword ptr[edi]
580 mov dword ptr[quotient], eax
583 mov eax, dword ptr[quotient+12]
584 mov dword ptr[edi+12], eax
585 mov eax, dword ptr[quotient+8]
586 mov dword ptr[edi+8], eax
587 mov eax, dword ptr[quotient+4]
588 mov dword ptr[edi+4], eax
589 mov eax, dword ptr[quotient]
590 mov dword ptr[edi], eax
597 mov dword ptr[REMAINDER+12], eax
598 mov dword ptr[REMAINDER+8], eax
599 mov dword ptr[REMAINDER+4], eax
600 mov dword ptr[REMAINDER], eax
605 shl dword ptr[QUOTIENT], 1
606 rcl dword ptr[QUOTIENT+4], 1
607 rcl dword ptr[QUOTIENT+8], 1
608 rcl dword ptr[QUOTIENT+12], 1
609 rcl dword ptr[REMAINDER], 1
610 rcl dword ptr[REMAINDER+4], 1
611 rcl dword ptr[REMAINDER+8], 1
612 rcl dword ptr[REMAINDER+12], 1
616 cmp dword ptr[REMAINDER+12], eax
620 cmp dword ptr[REMAINDER+8], eax
624 mov eax, dword ptr[REMAINDER+4]
625 cmp eax, dword ptr[divider+4]
629 mov eax, dword ptr[REMAINDER]
630 cmp eax, dword ptr[divider]
634 mov eax, dword ptr[divider]
635 sub dword ptr[REMAINDER], eax
636 mov eax, dword ptr[divider+4]
637 sbb dword ptr[REMAINDER+4], eax
639 sbb dword ptr[REMAINDER+8], eax
640 sbb dword ptr[REMAINDER+12], eax
642 add dword ptr[QUOTIENT], 1
643 adc dword ptr[QUOTIENT+4], 0
644 adc dword ptr[QUOTIENT+8], 0
645 adc dword ptr[QUOTIENT+12], 0
654 not dword ptr[edi+12]
655 not dword ptr[edi+ 8]
656 not dword ptr[edi+ 4]
658 add dword ptr[edi], 1
659 adc dword ptr[edi+ 4], 0
660 adc dword ptr[edi+ 8], 0
661 adc dword ptr[edi+12], 0
665 mov edx, dword ptr[edi+4]
666 mov eax, dword ptr[edi]
670#elif defined (_M_X64 )
672#pragma warning(disable: 4018)
673#pragma warning(disable: 4244)
674#pragma warning(disable: 4389)
675 uint64_t a = operant;
676 uint64_t b = multiplier;
677 uint64_t c = divider;
681 _BitScanReverse64(&shift, c);
687 a = _umul128(a, b, &b);
688 if (((b << shift) >> shift) != b)
691 return 0xFFFFFFFFFFFFFFFF;
693 b = __shiftleft128(a, b, shift);
701 div = (uint32_t)(c >> 32);
708 t0 = _umul128(c, (uint64_t)q1 << 32, &t1);
709 if (t1 < b || (t1 == b && t0 <= a))
721 return 0xFFFFFFFFFFFFFFFF;
725 t0 = ((b << 32) | (a >> 32)) / div;
732 t0 = _umul128(c, q0, &t1);
733 if (t1 < b || (t1 == b && t0 <= a))
738 return ((uint64_t)q1 << 32) | q0;
742 #error MulDiv64 is no supported!