diff options
Diffstat (limited to 'src/emu/attotime.h')
-rw-r--r-- | src/emu/attotime.h | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/emu/attotime.h b/src/emu/attotime.h new file mode 100644 index 00000000000..8d7395b9d42 --- /dev/null +++ b/src/emu/attotime.h @@ -0,0 +1,212 @@ +/*************************************************************************** + + attotime.h + + Support functions for working with attotime data. + + Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**************************************************************************** + + Attotime is an attosecond-accurate timing system implemented as + 96-bit integers. + + 1 second = 1e0 seconds + 1 millisecond = 1e-3 seconds + 1 microsecond = 1e-6 seconds + 1 nanosecond = 1e-9 seconds + 1 picosecond = 1e-12 seconds + 1 femtosecond = 1e-15 seconds + 1 attosecond = 1e-18 seconds + + This may seem insanely accurate, but it has its uses when multiple + clocks in the system are run by independent crystals. It is also + useful to compute the attotime for something small, say 1 clock tick, + and still have it be accurate and useful for scaling. + + Attotime consists of a 32-bit seconds count and a 64-bit attoseconds + count. Because the lower bits are kept as attoseconds and not as a + full 64-bit value, there is headroom to make some operations simpler. + +***************************************************************************/ + +#pragma once + +#ifndef __ATTOTIME_H__ +#define __ATTOTIME_H__ + +#include "mamecore.h" +#include <math.h> + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define ATTOSECONDS_PER_SECOND_SQRT ((attoseconds_t)1000000000) +#define ATTOSECONDS_PER_SECOND (ATTOSECONDS_PER_SECOND_SQRT * ATTOSECONDS_PER_SECOND_SQRT) +#define ATTOSECONDS_PER_MILLISECOND (ATTOSECONDS_PER_SECOND / 1000) +#define ATTOSECONDS_PER_MICROSECOND (ATTOSECONDS_PER_SECOND / 1000000) +#define ATTOSECONDS_PER_NANOSECOND (ATTOSECONDS_PER_SECOND / 1000000000) + +#define ATTOTIME_MAX_SECONDS ((seconds_t)1000000000) + + + +/*************************************************************************** + MACROS +***************************************************************************/ + +/* convert between a double and attoseconds */ +#define ATTOSECONDS_TO_DOUBLE(x) ((double)(x) * 1e-18) +#define DOUBLE_TO_ATTOSECONDS(x) ((attoseconds_t)((x) * 1e18)) + +/* convert between hertz (as a double) and attoseconds */ +#define ATTOSECONDS_TO_HZ(x) ((double)ATTOSECONDS_PER_SECOND / (double)(x)) +#define HZ_TO_ATTOSECONDS(x) ((attoseconds_t)(ATTOSECONDS_PER_SECOND / (x))) + +/* macros for converting other seconds types to attoseconds */ +#define ATTOSECONDS_IN_SEC(x) ((x) * ATTOSECONDS_PER_SECOND) +#define ATTOSECONDS_IN_MSEC(x) ((x) * ATTOSECONDS_PER_MILLISECOND) +#define ATTOSECONDS_IN_USEC(x) ((x) * ATTOSECONDS_PER_MICROSECOND) +#define ATTOSECONDS_IN_NSEC(x) ((x) * ATTOSECONDS_PER_NANOSECOND) + +/* macros for building attotimes from other types at runtime */ +#define ATTOTIME_IN_HZ(hz) attotime_make(0, HZ_TO_ATTOSECONDS(hz)) +#define ATTOTIME_IN_SEC(s) attotime_make((s) / 1, (s) % 1 /* mod here errors on doubles, which is intended */) +#define ATTOTIME_IN_MSEC(ms) attotime_make((ms) / 1000, ATTOSECONDS_IN_MSEC((ms) % 1000)) +#define ATTOTIME_IN_USEC(us) attotime_make((us) / 1000000, ATTOSECONDS_IN_USEC((us) % 1000000)) +#define ATTOTIME_IN_NSEC(ns) attotime_make((ns) / 1000000000, ATTOSECONDS_IN_NSEC((ns) % 1000000000)) + +/* macros for building attotimes from other types at compile time */ +#define STATIC_ATTOTIME_IN_HZ(hz) { 0, HZ_TO_ATTOSECONDS(hz) } +#define STATIC_ATTOTIME_IN_SEC(s) { (s) / 1, (s) % 1 /* mod here errors on doubles, which is intended */ } +#define STATIC_ATTOTIME_IN_MSEC(ms) { (ms) / 1000, ATTOSECONDS_IN_MSEC((ms) % 1000) } +#define STATIC_ATTOTIME_IN_USEC(us) { (us) / 1000000, ATTOSECONDS_IN_USEC((us) % 1000000) } +#define STATIC_ATTOTIME_IN_NSEC(ns) { (ns) / 1000000000, ATTOSECONDS_IN_NSEC((ns) % 1000000000) } + + +#define USEC_TO_ATTOSECONDS(us) ((attoseconds_t)((us) * ATTOSECONDS_PER_MICROSECOND)) + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* core components of the attotime structure */ +typedef INT64 attoseconds_t; +typedef INT32 seconds_t; + + +/* the attotime structure itself */ +typedef struct _attotime attotime; +struct _attotime +{ + seconds_t seconds; + attoseconds_t attoseconds; +}; + + + +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +/* constant times for zero and never */ +extern const attotime attotime_zero; +extern const attotime attotime_never; + + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +/* ----- conversion helpers ----- */ + +/* convert an attotime to attoseconds, clamping to maximum positive/negative values */ +attoseconds_t attotime_to_attoseconds(attotime _time); + + +/* ----- core math functions ----- */ + +/* add two attotimes */ +attotime attotime_add(attotime _time1, attotime _time2); + +/* add attoseconds to an attotime */ +attotime attotime_add_attoseconds(attotime _time1, attoseconds_t _attoseconds); + +/* subtract two attotimes */ +attotime attotime_sub(attotime _time1, attotime _time2); + +/* subtract attoseconds from an attotime */ +attotime attotime_sub_attoseconds(attotime _time1, attoseconds_t _attoseconds); + +/* multiply an attotime by a constant */ +attotime attotime_mul(attotime _time1, UINT32 factor); + +/* divide an attotime by a constant */ +attotime attotime_div(attotime _time1, UINT32 factor); + +/* compare two attotimes */ +int attotime_compare(attotime _time1, attotime _time2); + + +/* ----- misc utilities ----- */ + +/* return a temporary printable string describing an attotime */ +const char *attotime_string(attotime _time, int precision); + + + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*------------------------------------------------- + attotime_make - assemble an attotime from + seconds and attoseconds components +-------------------------------------------------*/ + +INLINE attotime attotime_make(seconds_t _secs, attoseconds_t _subsecs) +{ + attotime result; + result.seconds = _secs; + result.attoseconds = _subsecs; + return result; +} + + +/*------------------------------------------------- + attotime_to_double - convert from attotime + to double +-------------------------------------------------*/ + +INLINE double attotime_to_double(attotime _time) +{ + return (double)_time.seconds + ATTOSECONDS_TO_DOUBLE(_time.attoseconds); +} + + +/*------------------------------------------------- + double_to_attotime - convert from double to + attotime +-------------------------------------------------*/ + +INLINE attotime double_to_attotime(double _time) +{ + attotime result; + + /* set seconds to the integral part */ + result.seconds = floor(_time); + + /* set attoseconds to the fractional part */ + _time -= (double)result.seconds; + result.attoseconds = DOUBLE_TO_ATTOSECONDS(_time); + return result; +} + + +#endif /* __ATTOTIME_H__ */ |