// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include namespace Nz { constexpr Time::Time(Int64 nanoseconds) : m_nanoseconds(nanoseconds) { } template constexpr T Time::AsDuration() const { if constexpr (std::is_same_v) return std::chrono::nanoseconds(m_nanoseconds); //< make sure it's a no-op else return std::chrono::duration_cast(std::chrono::nanoseconds(m_nanoseconds)); } template constexpr T Time::AsSeconds() const { static_assert(std::is_floating_point_v); // TODO: Improve precision return AsMicroseconds() / T(1'000'000.0) + (m_nanoseconds % 1000) / T(1'000'000'000); } constexpr Int64 Time::AsMicroseconds() const { return m_nanoseconds / 1'000; } constexpr Int64 Time::AsMilliseconds() const { return m_nanoseconds / 1'000'000; } constexpr Int64 Time::AsNanoseconds() const { return m_nanoseconds; } constexpr Time& Time::operator+=(Time time) { m_nanoseconds += time.m_nanoseconds; return *this; } constexpr Time& Time::operator-=(Time time) { m_nanoseconds -= time.m_nanoseconds; return *this; } constexpr Time& Time::operator*=(Time time) { m_nanoseconds *= time.m_nanoseconds; return *this; } constexpr Time& Time::operator/=(Time time) { m_nanoseconds /= time.m_nanoseconds; return *this; } constexpr Time& Time::operator%=(Time time) { m_nanoseconds %= time.m_nanoseconds; return *this; } constexpr Time::operator Int64() const { return m_nanoseconds; } template constexpr Time Time::FromDuration(const std::chrono::duration& d) { return Nanoseconds(std::chrono::duration_cast(d).count()); } constexpr Time Time::Microsecond() { return Time(1'000); } constexpr Time Time::Microseconds(Int64 microseconds) { return Time(microseconds * 1'000); } constexpr Time Time::Millisecond() { return Time(1'000'000); } constexpr Time Time::Milliseconds(Int64 milliseconds) { return Time(milliseconds * 1'000'000); } constexpr Time Time::Nanosecond() { return Time(1); } constexpr Time Time::Nanoseconds(Int64 nanoseconds) { return Time(nanoseconds); } constexpr Time Time::Second() { return Time(1'000'000'000ull); } template constexpr Time Time::Seconds(T seconds) { if constexpr (std::is_floating_point_v) return Nanoseconds(static_cast(seconds * T(1'000'000'000.0))); else if constexpr (std::is_integral_v) return Nanoseconds(seconds * 1'000'000'000LL); else static_assert(AlwaysFalse(), "not an arithmetic type"); } constexpr Time Time::TickDuration(Int64 tickRate) { return Second() / Nanoseconds(tickRate); } constexpr Time Time::Zero() { return Time(0); } constexpr Time operator+(Time time) { return time; } constexpr Time operator-(Time time) { return Time(-time.m_nanoseconds); } constexpr Time operator+(Time lhs, Time rhs) { return Time(lhs.m_nanoseconds + rhs.m_nanoseconds); } constexpr Time operator-(Time lhs, Time rhs) { return Time(lhs.m_nanoseconds - rhs.m_nanoseconds); } constexpr Time operator*(Time lhs, Time rhs) { return Time(lhs.m_nanoseconds * rhs.m_nanoseconds); } constexpr Time operator/(Time lhs, Time rhs) { return Time(lhs.m_nanoseconds / rhs.m_nanoseconds); } constexpr Time operator%(Time lhs, Time rhs) { return Time(lhs.m_nanoseconds % rhs.m_nanoseconds); } constexpr bool operator==(Time lhs, Time rhs) { return lhs.m_nanoseconds == rhs.m_nanoseconds; } constexpr bool operator!=(Time lhs, Time rhs) { return lhs.m_nanoseconds != rhs.m_nanoseconds; } constexpr bool operator<(Time lhs, Time rhs) { return lhs.m_nanoseconds < rhs.m_nanoseconds; } constexpr bool operator<=(Time lhs, Time rhs) { return lhs.m_nanoseconds <= rhs.m_nanoseconds; } constexpr bool operator>(Time lhs, Time rhs) { return lhs.m_nanoseconds > rhs.m_nanoseconds; } constexpr bool operator>=(Time lhs, Time rhs) { return lhs.m_nanoseconds >= rhs.m_nanoseconds; } inline std::ostream& operator<<(std::ostream& out, Time time) { if (time > Time::Second()) return out << time.AsSeconds() << "s"; else { Int64 ns = time.AsNanoseconds(); if (time > Time::Millisecond()) return out << ns / 1'000'000.0 << "ms"; else if (time > Time::Microsecond()) return out << ns / 1'000.0 << "us"; else return out << ns << "ns"; } } inline bool Serialize(SerializationContext& context, Time time, TypeTag