Coverage Report

Created: 2026-09-14 07:01

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/aticqn.rs
Line
Count
Source
1
use crate::vm::{anp, c2s, s2c, trxp, zp};
2
3
use super::{IauAstrom, IauLdBody, ab, ldn};
4
5
///  Quick CIRS −> ICRS, multiple deflections
6
///
7
///  Quick CIRS to ICRS astrometric place transformation, given the star-
8
///  independent astrometry parameters plus a list of light-deflecting
9
///  bodies.
10
///
11
///  Use of this function is appropriate when efficiency is important and
12
///  where many star positions are all to be transformed for one date.
13
///  The star-independent astrometry parameters can be obtained by
14
///  calling one of the functions iauApci[13], iauApcg[13], iauApco[13]
15
///  or iauApcs[13].
16
///
17
///  If the only light-deflecting body to be taken into account is the
18
///  Sun, the iauAticq function can be used instead.
19
///
20
///  This function is part of the International Astronomical Union's
21
///  SOFA (Standards of Fundamental Astronomy) software collection.
22
///
23
///  Status:  support function.
24
///
25
///  Given:
26
///  ```
27
///     ri,di  double      CIRS RA,Dec (radians)
28
///     astrom iauASTROM*  star-independent astrometry parameters:
29
///      pmt    double       PM time interval (SSB, Julian years)
30
///      eb     double[3]    SSB to observer (vector, au)
31
///      eh     double[3]    Sun to observer (unit vector)
32
///      em     double       distance from Sun to observer (au)
33
///      v      double[3]    barycentric observer velocity (vector, c)
34
///      bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
35
///      bpn    double[3][3] bias-precession-nutation matrix
36
///      along  double       longitude + s' (radians)
37
///      xpl    double       polar motion xp wrt local meridian (radians)
38
///      ypl    double       polar motion yp wrt local meridian (radians)
39
///      sphi   double       sine of geodetic latitude
40
///      cphi   double       cosine of geodetic latitude
41
///      diurab double       magnitude of diurnal aberration vector
42
///      eral   double       "local" Earth rotation angle (radians)
43
///      refa   double       refraction constant A (radians)
44
///      refb   double       refraction constant B (radians)
45
///     n      int          number of bodies (Note 3)
46
///     b      iauLDBODY[n] data for each of the n bodies (Notes 3,4):
47
///      bm     double       mass of the body (solar masses, Note 5)
48
///      dl     double       deflection limiter (Note 6)
49
///      pv     [2][3]       barycentric PV of the body (au, au/day)
50
///  ```
51
///  Returned:
52
///  ```
53
///     rc,dc  double     ICRS astrometric RA,Dec (radians)
54
///  ```
55
///  Notes:
56
///
57
///  1) Iterative techniques are used for the aberration and light
58
///     deflection corrections so that the functions iauAticqn and
59
///     iauAtciqn are accurate inverses; even at the edge of the Sun's
60
///     disk the discrepancy is only about 1 nanoarcsecond.
61
///
62
///  2) If the only light-deflecting body to be taken into account is the
63
///     Sun, the iauAticq function can be used instead.
64
///
65
///  3) The struct b contains n entries, one for each body to be
66
///     considered.  If n = 0, no gravitational light deflection will be
67
///     applied, not even for the Sun.
68
///
69
///  4) The struct b should include an entry for the Sun as well as for
70
///     any planet or other body to be taken into account.  The entries
71
///     should be in the order in which the light passes the body.
72
///
73
///  5) In the entry in the b struct for body i, the mass parameter
74
///     b[i].bm can, as required, be adjusted in order to allow for such
75
///     effects as quadrupole field.
76
///
77
///  6) The deflection limiter parameter b[i].dl is phi^2/2, where phi is
78
///     the angular separation (in radians) between star and body at
79
///     which limiting is applied.  As phi shrinks below the chosen
80
///     threshold, the deflection is artificially reduced, reaching zero
81
///     for phi = 0.   Example values suitable for a terrestrial
82
///     observer, together with masses, are as follows:
83
///  ```
84
///        body i     b[i].bm        b[i].dl
85
///
86
///        Sun        1.0            6e-6
87
///        Jupiter    0.00095435     3e-9
88
///        Saturn     0.00028574     3e-10
89
///  ```
90
///  7) For efficiency, validation of the contents of the b array is
91
///     omitted.  The supplied masses must be greater than zero, the
92
///     position and velocity vectors must be right, and the deflection
93
///     limiter greater than zero.
94
///
95
///  Called:
96
///  ```
97
///     iauS2c       spherical coordinates to unit vector
98
///     iauTrxp      product of transpose of r-matrix and p-vector
99
///     iauZp        zero p-vector
100
///     iauAb        stellar aberration
101
///     iauLdn       light deflection by n bodies
102
///     iauC2s       p-vector to spherical
103
///     iauAnp       normalize angle into range +/- pi
104
///  ```
105
0
pub fn aticqn(ri: f64, di: f64, astrom: &mut IauAstrom, n: i32, b: &[IauLdBody]) -> (f64, f64) {
106
    let pi: [f64; 3];
107
0
    let mut ppr = [0.0; 3];
108
0
    let mut pnat = [0.0; 3];
109
0
    let mut pco = [0.0; 3];
110
    let mut w;
111
0
    let mut d = [0.0; 3];
112
0
    let mut before = [0.0; 3];
113
    let mut r2;
114
    let mut r;
115
    let mut after: [f64; 3];
116
117
    // CIRS RA,Dec to Cartesian.
118
0
    pi = s2c(ri, di);
119
120
    // Bias-precession-nutation, giving GCRS proper direction.
121
0
    trxp(&astrom.bpn, &pi, &mut ppr);
122
123
    // Aberration, giving GCRS natural direction.
124
0
    for _ in 0..2 {
125
0
        r2 = 0.0;
126
0
        for i in 0..3 {
127
0
            w = ppr[i] - d[i];
128
0
            before[i] = w;
129
0
            r2 += w * w;
130
0
        }
131
0
        r = r2.sqrt();
132
0
        for i in 0..3 {
133
0
            before[i] /= r;
134
0
        }
135
0
        after = ab(&before, &astrom.v, astrom.em, astrom.bm1);
136
0
        r2 = 0.0;
137
0
        for i in 0..3 {
138
0
            d[i] = after[i] - before[i];
139
0
            w = ppr[i] - d[i];
140
0
            pnat[i] = w;
141
0
            r2 += w * w;
142
0
        }
143
0
        r = r2.sqrt();
144
0
        for i in 0..3 {
145
0
            pnat[i] /= r;
146
0
        }
147
    }
148
149
    // Light deflection, giving BCRS coordinate direction.
150
0
    zp(&mut d);
151
0
    for _ in 0..5 {
152
0
        r2 = 0.0;
153
0
        for i in 0..3 {
154
0
            w = pnat[i] - d[i];
155
0
            before[i] = w;
156
0
            r2 += w * w;
157
0
        }
158
0
        r = r2.sqrt();
159
0
        for i in 0..3 {
160
0
            before[i] /= r;
161
0
        }
162
0
        after = ldn(n, b, &astrom.eb, &before);
163
0
        r2 = 0.0;
164
0
        for i in 0..3 {
165
0
            d[i] = after[i] - before[i];
166
0
            w = pnat[i] - d[i];
167
0
            pco[i] = w;
168
0
            r2 += w * w;
169
0
        }
170
0
        r = r2.sqrt();
171
0
        for i in 0..3 {
172
0
            pco[i] /= r;
173
0
        }
174
    }
175
176
    // ICRS astrometric RA,Dec.
177
0
    let (w, dc) = c2s(&pco);
178
179
0
    (anp(w), dc)
180
0
}