1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//
// GENERATED FILE
//
use super::*;
use f2rust_std::*;
struct SaveVars {
ZZDIV: f64,
LOGNUM: f64,
LOGDEN: f64,
EXPNT: f64,
FIRST: bool,
}
impl SaveInit for SaveVars {
fn new() -> Self {
let mut ZZDIV: f64 = 0.0;
let mut LOGNUM: f64 = 0.0;
let mut LOGDEN: f64 = 0.0;
let mut EXPNT: f64 = 0.0;
let mut FIRST: bool = false;
FIRST = true;
Self {
ZZDIV,
LOGNUM,
LOGDEN,
EXPNT,
FIRST,
}
}
}
//$Procedure ZZDIV ( Safer division )
pub fn ZZDIV(NUMR: f64, DENOM: f64, ctx: &mut Context) -> f2rust_std::Result<f64> {
let save = ctx.get_vars::<SaveVars>();
let save = &mut *save.borrow_mut();
//
// SPICELIB functions
//
//
// Local variables
//
//
// The bounds on the potential result of the calculation.
//
//
// First entry flag.
//
//
// Return on error.
//
if RETURN(ctx) {
save.ZZDIV = 0.0;
return Ok(save.ZZDIV);
}
//
// Participate in error tracing.
//
CHKIN(b"ZZDIV", ctx)?;
//
// Calculate the bounds parameter on first entry.
// The double precision maximum value has the form
// "d*(10**EXPNT)." The value of interest is "EXPNT."
//
if save.FIRST {
save.FIRST = false;
//
// A "floor" evaluation.
//
save.EXPNT = ((f64::log10(DPMAX()) as i32) as f64);
}
//
// If the denominator is zero, return zero and signal an error.
// This is equivalent to a signaling NaN (not-a-number) for
// the 0/0 case.
//
if (DENOM == 0.0) {
save.ZZDIV = 0.0;
SETMSG(b"Numerical divide by zero event. Numerator value #1.", ctx);
ERRDP(b"#1", NUMR, ctx);
SIGERR(b"SPICE(DIVIDEBYZERO)", ctx)?;
CHKOUT(b"ZZDIV", ctx)?;
return Ok(save.ZZDIV);
}
//
// If the numerator is zero, the division is zero. DENOM
// is known non-zero.
//
if (NUMR == 0.0) {
save.ZZDIV = 0.0;
CHKOUT(b"ZZDIV", ctx)?;
return Ok(save.ZZDIV);
}
//
// Calculate base 10 logarithms of the absolute value of the
// numerator and denominator. Recall the base 10 log of a negative
// real is a complex number (an irritating reality). Our interest
// is the magnitude of the result, not the sign.
//
// An earlier check returned if NUMR or DENOM equals zero, so the
// LOG10 call is safe from an infinite return value. An infinite
// return value defeats the purpose of this routine.
//
save.LOGNUM = f64::log10(f64::abs(NUMR));
save.LOGDEN = f64::log10(f64::abs(DENOM));
//
// Local possible overflow check.
//
if ((save.LOGNUM - save.LOGDEN) > save.EXPNT) {
save.ZZDIV = 0.0;
SETMSG(
b"Numerical overflow event. Numerator value #1, denominator value #2.",
ctx,
);
ERRDP(b"#1", NUMR, ctx);
ERRDP(b"#2", DENOM, ctx);
SIGERR(b"SPICE(NUMERICOVERFLOW)", ctx)?;
CHKOUT(b"ZZDIV", ctx)?;
return Ok(save.ZZDIV);
}
//
// Local possible underflow check. Accept this may occur,
// return a zero.
//
if ((save.LOGNUM - save.LOGDEN) < -(save.EXPNT - 1.0)) {
save.ZZDIV = 0.0;
CHKOUT(b"ZZDIV", ctx)?;
return Ok(save.ZZDIV);
}
//
// This operation should be safe. Probably.
//
save.ZZDIV = (NUMR / DENOM);
CHKOUT(b"ZZDIV", ctx)?;
Ok(save.ZZDIV)
}