Skip to content

Commit

Permalink
Merge pull request #132 from nyx-space/issue-128
Browse files Browse the repository at this point in the history
Changes pre-v.3.3.0
  • Loading branch information
ChristopherRabotin authored Jul 31, 2022
2 parents 4ea9cd5 + ec8a0f8 commit bec98a0
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 22 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ readme = "README.md"
license = "Apache-2.0"

[dependencies]
libm = "0.2.2"
serde = {version = "1.0.137", optional = true}
regex = {version = "1.5.5", optional = true}
serde_derive = {version = "1.0.137", optional = true}
[dependencies.num-traits]
version = "0.2"
default-features = false

[dev-dependencies]
criterion = "0.3.5"
Expand Down
16 changes: 7 additions & 9 deletions src/duration.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use libm::{fabs, floor, pow};

#[cfg(feature = "std")]
use crate::ParsingErrors;
use crate::{
Expand Down Expand Up @@ -200,7 +198,7 @@ impl Duration {
/// Create a new duration from the truncated nanoseconds (+/- 2927.1 years of duration)
pub fn from_truncated_nanoseconds(nanos: i64) -> Self {
if nanos < 0 {
let ns = nanos.abs() as u64;
let ns = nanos.unsigned_abs();
let extra_centuries = ns.div_euclid(NANOSECONDS_PER_CENTURY);
if extra_centuries > i16::MAX as u64 {
Self::MIN
Expand All @@ -212,7 +210,7 @@ impl Duration {
)
}
} else {
Self::from_parts(0, nanos.abs() as u64)
Self::from_parts(0, nanos.unsigned_abs())
}
}

Expand Down Expand Up @@ -493,14 +491,14 @@ impl Mul<f64> for Duration {
let ten: f64 = 10.0;

loop {
if fabs(floor(new_val) - new_val) < f64::EPSILON {
if (new_val.floor() - new_val).abs() < f64::EPSILON {
// Yay, we've found the precision of this number
break;
}
// Multiply by the precision
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b760579f103b7192c20413ebbe167b90
p += 1;
new_val = q * pow(ten, f64::from(p));
new_val = q * ten.powi(p);
}

Duration::from_total_nanoseconds(
Expand Down Expand Up @@ -551,7 +549,7 @@ impl Mul<f64> for Unit {
Unit::Microsecond => q * (NANOSECONDS_PER_MICROSECOND as f64),
Unit::Nanosecond => q,
};
if fabs(total_ns) < (i64::MAX as f64) {
if total_ns.abs() < (i64::MAX as f64) {
Duration::from_truncated_nanoseconds(total_ns as i64)
} else {
Duration::from_total_nanoseconds(total_ns as i128)
Expand Down Expand Up @@ -581,7 +579,7 @@ macro_rules! impl_ops_for_type {
Freq::KiloHertz => NANOSECONDS_PER_MILLISECOND as f64 / (q as f64),
Freq::Hertz => (NANOSECONDS_PER_SECOND as f64) / (q as f64),
};
if fabs(total_ns) < (i64::MAX as f64) {
if total_ns.abs() < (i64::MAX as f64) {
Duration::from_truncated_nanoseconds(total_ns as i64)
} else {
Duration::from_total_nanoseconds(total_ns as i128)
Expand Down Expand Up @@ -655,7 +653,7 @@ impl fmt::LowerExp for Duration {
// Prints the duration with appropriate units
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let seconds_f64 = self.in_seconds();
let seconds_f64_abs = fabs(seconds_f64);
let seconds_f64_abs = seconds_f64.abs();
if seconds_f64_abs < 1e-5 {
fmt::Display::fmt(&(seconds_f64 * 1e9), f)?;
write!(f, " ns")
Expand Down
100 changes: 89 additions & 11 deletions src/epoch.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use libm::{fabs, sin, trunc};

use crate::duration::{Duration, Unit};
use crate::{
Errors, TimeSystem, DAYS_GPS_TAI_OFFSET, ET_EPOCH_S, J1900_OFFSET, J2000_OFFSET, MJD_OFFSET,
Expand Down Expand Up @@ -303,9 +301,9 @@ impl Epoch {
let g_rad = (PI / 180.0) * (357.528 + 35_999.050 * tt_centuries_j2k);

// Decimal does not provide trig functions, so let's define the parts of the trig separately.
let inner = g_rad + 0.0167 * sin(g_rad);
let inner = g_rad + 0.0167 * g_rad.sin();

Self(tt_duration + ((ET_EPOCH_S as f64) - (0.001_658 * sin(inner))) * Unit::Second)
Self(tt_duration + ((ET_EPOCH_S as f64) - (0.001_658 * inner.sin())) * Unit::Second)
}

#[must_use]
Expand Down Expand Up @@ -590,7 +588,7 @@ impl Epoch {

#[must_use]
/// Returns this time in a Duration past J1900 counted in UTC
fn as_utc_duration(&self) -> Duration {
pub fn as_utc_duration(&self) -> Duration {
let cnt = self.get_num_leap_seconds();
// TAI = UTC + leap_seconds <=> UTC = TAI - leap_seconds
self.0 + i64::from(-cnt) * Unit::Second
Expand Down Expand Up @@ -815,23 +813,23 @@ impl Epoch {
let inner = self.inner_g_rad();

self.as_tt_duration() - (ET_EPOCH_S * Unit::Second)
+ (0.001_658 * sin(inner)) * Unit::Second
+ (0.001_658 * inner.sin()) * Unit::Second
}

#[must_use]
/// Returns the Dynamic Barycentric Time (TDB) (higher fidelity SPICE ephemeris time) whose epoch is 2000 JAN 01 noon TAI (cf. <https://gssc.esa.int/navipedia/index.php/Transformations_between_Time_Systems#TDT_-_TDB.2C_TCB>)
pub fn as_tdb_seconds(&self) -> f64 {
// Note that we redo the calculation of as_tdb_duration to save computational cost
let inner = self.inner_g_rad();
self.as_tt_seconds() - (ET_EPOCH_S as f64) + (0.001_658 * sin(inner))
self.as_tt_seconds() - (ET_EPOCH_S as f64) + (0.001_658 * inner.sin())
}

/// For TDB computation, we're using f64 only because BigDecimal is far too slow for Nyx (uses FromStr).
fn inner_g_rad(&self) -> f64 {
use core::f64::consts::PI;
let g_rad = (PI / 180.0) * (357.528 + 35_999.050 * self.as_tt_centuries_j2k());

g_rad + 0.0167 * sin(g_rad)
g_rad + 0.0167 * g_rad.sin()
}

#[must_use]
Expand All @@ -853,7 +851,7 @@ impl Epoch {
#[must_use]
pub fn as_jde_tdb_duration(&self) -> Duration {
let inner = self.inner_g_rad();
let tdb_delta = (0.001_658 * sin(inner)) * Unit::Second;
let tdb_delta = (0.001_658 * inner.sin()) * Unit::Second;
self.as_jde_tt_duration() + tdb_delta
}

Expand Down Expand Up @@ -1327,6 +1325,83 @@ impl fmt::LowerHex for Epoch {
}
}

impl fmt::UpperHex for Epoch {
/// Prints the Epoch in TT
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ts = TimeSystem::TT;
let (y, mm, dd, hh, min, s, nanos) = Self::compute_gregorian(self.as_tt_seconds());
if nanos == 0 {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02} {:?}",
y, mm, dd, hh, min, s, ts
)
} else {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{} {:?}",
y, mm, dd, hh, min, s, nanos, ts
)
}
}
}

impl fmt::LowerExp for Epoch {
/// Prints the Epoch in TDB
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ts = TimeSystem::TDB;
let (y, mm, dd, hh, min, s, nanos) = Self::compute_gregorian(self.as_tdb_seconds());
if nanos == 0 {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02} {:?}",
y, mm, dd, hh, min, s, ts
)
} else {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{} {:?}",
y, mm, dd, hh, min, s, nanos, ts
)
}
}
}

impl fmt::UpperExp for Epoch {
/// Prints the Epoch in ET
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ts = TimeSystem::ET;
let (y, mm, dd, hh, min, s, nanos) = Self::compute_gregorian(self.as_et_seconds());
if nanos == 0 {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02} {:?}",
y, mm, dd, hh, min, s, ts
)
} else {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{} {:?}",
y, mm, dd, hh, min, s, nanos, ts
)
}
}
}

impl fmt::Pointer for Epoch {
/// Prints the Epoch in UNIX
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_unix_seconds())
}
}

impl fmt::Octal for Epoch {
/// Prints the Epoch in GPS
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_gpst_nanoseconds().unwrap())
}
}

#[must_use]
/// Returns true if the provided Gregorian date is valid. Leap second days may have 60 seconds.
pub fn is_gregorian_valid(
Expand Down Expand Up @@ -1379,7 +1454,7 @@ fn div_rem_f64(me: f64, rhs: f64) -> (i32, f64) {
}

fn div_euclid_f64(lhs: f64, rhs: f64) -> f64 {
let q = trunc(lhs / rhs);
let q = (lhs / rhs).trunc();
if lhs % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
}
Expand All @@ -1389,7 +1464,7 @@ fn div_euclid_f64(lhs: f64, rhs: f64) -> f64 {
fn rem_euclid_f64(lhs: f64, rhs: f64) -> f64 {
let r = lhs % rhs;
if r < 0.0 {
r + fabs(rhs)
r + rhs.abs()
} else {
r
}
Expand Down Expand Up @@ -1790,6 +1865,7 @@ mod tests {
gps_epoch.as_gregorian_str(TimeSystem::TAI),
"1980-01-06T00:00:19 TAI"
);
assert_eq!(format!("{:o}", gps_epoch), "0");
}
assert_eq!(
gps_epoch.as_tai_seconds(),
Expand Down Expand Up @@ -1847,6 +1923,8 @@ mod tests {
unix_epoch.as_gregorian_str(TimeSystem::TAI),
"1970-01-01T00:00:00 TAI"
);
// Print as UNIX seconds
assert_eq!(format!("{:p}", unix_epoch), "0");
}
assert_eq!(
unix_epoch.as_tai_seconds(),
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub mod prelude {
pub use {Duration, Epoch, Freq, Frequencies, TimeSeries, TimeUnits, Unit};
}

extern crate libm;
extern crate num_traits;

#[cfg(feature = "std")]
extern crate serde;
Expand Down

0 comments on commit bec98a0

Please sign in to comment.