Coverage Report

Created: 2026-09-04 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sofars-0.6.1/src/astro/starpm.rs
Line
Count
Source
1
use crate::{
2
    consts::DC,
3
    vm::{pdp, pm, pvu},
4
};
5
6
use super::{pvstar, starpv};
7
8
///  Star proper motion:  update star catalog data for space motion.
9
///
10
///  This function is part of the International Astronomical Union's
11
///  SOFA (Standards of Fundamental Astronomy) software collection.
12
///
13
///  Status:  support function.
14
///
15
///  Given:
16
///     ra1    double     right ascension (radians), before
17
///     dec1   double     declination (radians), before
18
///     pmr1   double     RA proper motion (radians/year), before
19
///     pmd1   double     Dec proper motion (radians/year), before
20
///     px1    double     parallax (arcseconds), before
21
///     rv1    double     radial velocity (km/s, +ve = receding), before
22
///     ep1a   double     "before" epoch, part A (Note 1)
23
///     ep1b   double     "before" epoch, part B (Note 1)
24
///     ep2a   double     "after" epoch, part A (Note 1)
25
///     ep2b   double     "after" epoch, part B (Note 1)
26
///
27
///  Returned:
28
///     ra2    double     right ascension (radians), after
29
///     dec2   double     declination (radians), after
30
///     pmr2   double     RA proper motion (radians/year), after
31
///     pmd2   double     Dec proper motion (radians/year), after
32
///     px2    double     parallax (arcseconds), after
33
///     rv2    double     radial velocity (km/s, +ve = receding), after
34
///
35
///  Returned (function value):
36
///            int        status:
37
///                          -1 = system error (should not occur)
38
///                           0 = no warnings or errors
39
///                           1 = distance overridden (Note 6)
40
///                           2 = excessive velocity (Note 7)
41
///                           4 = solution didn't converge (Note 8)
42
///                        else = binary logical OR of the above warnings
43
///
44
///  Notes:
45
///
46
///  1) The starting and ending TDB dates ep1a+ep1b and ep2a+ep2b are
47
///     Julian Dates, apportioned in any convenient way between the two
48
///     parts (A and B).  For example, JD(TDB)=2450123.7 could be
49
///     expressed in any of these ways, among others:
50
///
51
///            epNa            epNb
52
///
53
///         2450123.7           0.0       (JD method)
54
///         2451545.0       -1421.3       (J2000 method)
55
///         2400000.5       50123.2       (MJD method)
56
///         2450123.5           0.2       (date & time method)
57
///
58
///     The JD method is the most natural and convenient to use in cases
59
///     where the loss of several decimal digits of resolution is
60
///     acceptable.  The J2000 method is best matched to the way the
61
///     argument is handled internally and will deliver the optimum
62
///     resolution.  The MJD method and the date & time methods are both
63
///     good compromises between resolution and convenience.
64
///
65
///  2) In accordance with normal star-catalog conventions, the object's
66
///     right ascension and declination are freed from the effects of
67
///     secular aberration.  The frame, which is aligned to the catalog
68
///     equator and equinox, is Lorentzian and centered on the SSB.
69
///
70
///     The proper motions are the rate of change of the right ascension
71
///     and declination at the catalog epoch and are in radians per TDB
72
///     Julian year.
73
///
74
///     The parallax and radial velocity are in the same frame.
75
///
76
///  3) Care is needed with units.  The star coordinates are in radians
77
///     and the proper motions in radians per Julian year, but the
78
///     parallax is in arcseconds.
79
///
80
///  4) The RA proper motion is in terms of coordinate angle, not true
81
///     angle.  If the catalog uses arcseconds for both RA and Dec proper
82
///     motions, the RA proper motion will need to be divided by cos(Dec)
83
///     before use.
84
///
85
///  5) Straight-line motion at constant speed, in the inertial frame,
86
///     is assumed.
87
///
88
///  6) An extremely small (or zero or negative) parallax is interpreted
89
///     to mean that the object is on the "celestial sphere", the radius
90
///     of which is an arbitrary (large) value (see the iauStarpv
91
///     function for the value used).  When the distance is overridden in
92
///     this way, the status, initially zero, has 1 added to it.
93
///
94
///  7) If the space velocity is a significant fraction of c (see the
95
///     constant VMAX in the function iauStarpv), it is arbitrarily set
96
///     to zero.  When this action occurs, 2 is added to the status.
97
///
98
///  8) The relativistic adjustment carried out in the iauStarpv function
99
///     involves an iterative calculation.  If the process fails to
100
///     converge within a set number of iterations, 4 is added to the
101
///     status.
102
///
103
///  Called:
104
///     iauStarpv    star catalog data to space motion pv-vector
105
///     iauPvu       update a pv-vector
106
///     iauPdp       scalar product of two p-vectors
107
///     iauPvstar    space motion pv-vector to star catalog data
108
///
109
0
pub fn starpm(
110
0
    ra1: f64,
111
0
    dec1: f64,
112
0
    pmr1: f64,
113
0
    pmd1: f64,
114
0
    px1: f64,
115
0
    rv1: f64,
116
0
    ep1a: f64,
117
0
    ep1b: f64,
118
0
    ep2a: f64,
119
0
    ep2b: f64,
120
0
) -> Result<([f64; 6], i32), i32> {
121
    /* RA,Dec etc. at the "before" epoch to space motion pv-vector. */
122
0
    let (pv1, j1) = starpv(ra1, dec1, pmr1, pmd1, px1, rv1);
123
124
    /* Light time when observed (days). */
125
0
    let tl1 = pm(pv1[0]) / DC;
126
127
    /* Time interval, "before" to "after" (days). */
128
0
    let dt = (ep2a - ep1a) + (ep2b - ep1b);
129
130
    /* Move star along track from the "before" observed position to the */
131
    /* "after" geometric position. */
132
0
    let pv = pvu(dt + tl1, &pv1);
133
134
    /* From this geometric position, deduce the observed light time (days) */
135
    /* at the "after" epoch (with theoretically unneccessary error check). */
136
0
    let r2 = pdp(&pv[0], &pv[0]);
137
0
    let rdv = pdp(&pv[0], &pv[1]);
138
0
    let v2 = pdp(&pv[1], &pv[1]);
139
0
    let c2mv2 = DC * DC - v2;
140
0
    if c2mv2 <= 0.0 {
141
0
        return Err(-1);
142
0
    }
143
0
    let tl2 = (-rdv + (rdv * rdv + c2mv2 * r2).sqrt()) / c2mv2;
144
145
    /* Move the position along track from the observed place at the */
146
    /* "before" epoch to the observed place at the "after" epoch. */
147
0
    let pv2 = pvu(dt + (tl1 - tl2), &pv1);
148
149
    /* Space motion pv-vector to RA,Dec etc. at the "after" epoch. */
150
0
    let (j2, ra2, dec2, pmr2, pmd2, px2, rv2) = match pvstar(&pv2) {
151
0
        Ok(res) => (0, res[0], res[1], res[2], res[3], res[4], res[5]),
152
0
        Err(_) => (-1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
153
    };
154
155
    /* Final status. */
156
0
    let j = if j2 == 0 { j1 } else { -1 };
157
158
0
    if j < 0 {
159
0
        Err(j)
160
    } else {
161
0
        Ok(([ra2, dec2, pmr2, pmd2, px2, rv2], j))
162
    }
163
0
}