Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 053049c

Browse files
committed
Basic domain
1 parent f40e33c commit 053049c

File tree

5 files changed

+568
-4
lines changed

5 files changed

+568
-4
lines changed

crates/libm-test/src/domain.rs

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
#![allow(unused)]
2+
3+
// todo: combine these modules with those in MPFR so we only have one ty for each function.
4+
5+
use std::fmt;
6+
use std::ops::{self, Bound};
7+
8+
use crate::Float;
9+
10+
pub trait Domain<T>
11+
where
12+
T: Copy + fmt::Debug + ops::Add<Output = T> + ops::Sub<Output = T> + PartialOrd + 'static,
13+
{
14+
/// The region for which the function is defined. Ignores poles.
15+
const DEFINED: (Bound<T>, Bound<T>);
16+
17+
/// The region, if any, for which the function repeats. Used to test within.
18+
const PERIODIC: Option<(Bound<T>, Bound<T>)> = None;
19+
20+
/// from -> to mapping
21+
fn defined_asymptotes() -> impl Iterator<Item = (T, T)> {
22+
std::iter::empty()
23+
}
24+
25+
/// Check if an input is a pole or branch point.
26+
fn is_pole(_input: T) -> bool {
27+
false
28+
}
29+
30+
/// Points to check closer around, often zeros of the derivative.
31+
fn check_points() -> impl Iterator<Item = T> {
32+
std::iter::empty()
33+
}
34+
35+
fn nan_handling(input: T) -> T {
36+
input
37+
}
38+
39+
fn period() -> Option<T> {
40+
if Self::PERIODIC.is_none() {
41+
return None;
42+
}
43+
44+
let start = Self::period_start();
45+
let end = Self::period_end();
46+
if start > end { Some(start - end) } else { Some(end - start) }
47+
}
48+
49+
fn period_start() -> T {
50+
let start = Self::PERIODIC.unwrap().0;
51+
let (Bound::Included(start) | Bound::Excluded(start)) = start else {
52+
panic!("`Unbounded` in period {:?}", Self::PERIODIC);
53+
};
54+
start
55+
}
56+
57+
fn period_end() -> T {
58+
let end = Self::PERIODIC.unwrap().1;
59+
let (Bound::Included(end) | Bound::Excluded(end)) = end else {
60+
panic!("`Unbounded` in period {:?}", Self::PERIODIC);
61+
};
62+
end
63+
}
64+
}
65+
66+
/// Use for anything basic, no bounds, no asymptotes, etc.
67+
pub struct Unbounded;
68+
69+
impl<F: Float> Domain<F> for Unbounded {
70+
const DEFINED: (Bound<F>, Bound<F>) = unbounded();
71+
}
72+
73+
pub mod asin {
74+
use super::*;
75+
pub struct D;
76+
77+
impl<F: Float> Domain<F> for D {
78+
const DEFINED: (Bound<F>, Bound<F>) =
79+
(Bound::Included(F::NEG_ONE), Bound::Included(F::ONE));
80+
}
81+
}
82+
83+
pub mod acos {
84+
use super::*;
85+
pub struct D;
86+
87+
impl<F: Float> Domain<F> for D {
88+
const DEFINED: (Bound<F>, Bound<F>) =
89+
(Bound::Included(F::NEG_ONE), Bound::Included(F::ONE));
90+
}
91+
}
92+
93+
pub mod atan {
94+
pub use super::Unbounded as D;
95+
}
96+
97+
pub mod asinh {
98+
pub use super::Unbounded as D;
99+
}
100+
101+
pub mod acosh {
102+
use super::*;
103+
pub struct D;
104+
105+
impl<F: Float> Domain<F> for D {
106+
const DEFINED: (Bound<F>, Bound<F>) = (Bound::Included(F::ONE), Bound::Unbounded);
107+
}
108+
}
109+
110+
pub mod atanh {
111+
use super::*;
112+
pub struct D;
113+
114+
impl<F: Float> Domain<F> for D {
115+
const DEFINED: (Bound<F>, Bound<F>) =
116+
(Bound::Excluded(F::NEG_ONE), Bound::Excluded(F::ONE));
117+
118+
fn defined_asymptotes() -> impl Iterator<Item = (F, F)> {
119+
[(F::NEG_ONE, F::CONSTS.neg_inf), (F::ONE, F::CONSTS.inf)].into_iter()
120+
}
121+
}
122+
}
123+
124+
pub mod sin {
125+
use super::*;
126+
pub struct D;
127+
128+
impl<F: Float> Domain<F> for D {
129+
const DEFINED: (Bound<F>, Bound<F>) = unbounded();
130+
131+
const PERIODIC: Option<(Bound<F>, Bound<F>)> =
132+
Some((Bound::Excluded(F::CONSTS.neg_pi), Bound::Included(F::CONSTS.pi)));
133+
134+
fn check_points() -> impl Iterator<Item = F> {
135+
[-F::CONSTS.pi, -F::CONSTS.frac_pi_2, F::CONSTS.frac_pi_2, F::CONSTS.pi].into_iter()
136+
}
137+
}
138+
}
139+
140+
pub mod cos {
141+
pub use super::sin::D;
142+
}
143+
144+
pub mod tan {
145+
pub use super::sin::D;
146+
}
147+
148+
pub mod cosh {
149+
pub use super::Unbounded as D;
150+
}
151+
152+
pub mod sinh {
153+
pub use super::Unbounded as D;
154+
}
155+
156+
pub mod tanh {
157+
pub use super::Unbounded as D;
158+
}
159+
160+
pub mod cbrt {
161+
pub use super::Unbounded as D;
162+
}
163+
164+
pub mod ceil {
165+
pub use super::Unbounded as D;
166+
}
167+
168+
pub mod floor {
169+
pub use super::Unbounded as D;
170+
}
171+
172+
pub mod erf {
173+
pub use super::Unbounded as D;
174+
}
175+
176+
pub mod exp {
177+
pub use super::Unbounded as D;
178+
}
179+
180+
pub mod exp10 {
181+
pub use super::exp::D;
182+
}
183+
184+
pub mod exp2 {
185+
pub use super::exp::D;
186+
}
187+
188+
pub mod expm1 {
189+
pub use super::Unbounded as D;
190+
}
191+
192+
pub mod fabs {
193+
pub use super::Unbounded as D;
194+
}
195+
196+
pub mod frexp {
197+
pub use super::Unbounded as D;
198+
}
199+
200+
pub mod j0 {
201+
pub use super::Unbounded as D;
202+
}
203+
204+
pub mod j1 {
205+
pub use super::Unbounded as D;
206+
}
207+
208+
pub mod lgamma {}
209+
pub mod lgamma_r {}
210+
211+
pub mod log {
212+
use super::*;
213+
pub struct D;
214+
215+
impl<F: Float> Domain<F> for D {
216+
const DEFINED: (Bound<F>, Bound<F>) = strictly_positive();
217+
218+
fn defined_asymptotes() -> impl Iterator<Item = (F, F)> {
219+
[(F::ZERO, F::CONSTS.neg_inf)].into_iter()
220+
}
221+
}
222+
}
223+
224+
pub mod log10 {
225+
pub use super::log::D;
226+
}
227+
228+
pub mod log1p {
229+
use super::*;
230+
pub struct D;
231+
232+
impl<F: Float> Domain<F> for D {
233+
const DEFINED: (Bound<F>, Bound<F>) = (Bound::Excluded(F::NEG_ONE), Bound::Unbounded);
234+
235+
fn defined_asymptotes() -> impl Iterator<Item = (F, F)> {
236+
[(F::NEG_ONE, F::CONSTS.neg_inf)].into_iter()
237+
}
238+
}
239+
}
240+
241+
pub mod log2 {
242+
pub use super::log::D;
243+
}
244+
245+
pub mod modf {}
246+
pub mod nextafter {}
247+
248+
pub mod rint {
249+
pub use super::log::D;
250+
}
251+
pub mod round {
252+
pub use super::Unbounded as D;
253+
}
254+
pub mod sincos {
255+
pub use super::sin::D;
256+
}
257+
258+
pub mod sqrt {
259+
use super::*;
260+
pub struct D;
261+
262+
impl<F: Float> Domain<F> for D {
263+
const DEFINED: (Bound<F>, Bound<F>) = positive();
264+
}
265+
}
266+
267+
pub mod tgamma {}
268+
269+
pub mod trunc {
270+
pub use super::Unbounded as D;
271+
}
272+
273+
pub mod atan2 {}
274+
pub mod copysign {}
275+
pub mod fdim {}
276+
pub mod fma {}
277+
pub mod fmax {}
278+
pub mod fmin {}
279+
pub mod fmod {}
280+
pub mod hypot {}
281+
pub mod ilogb {}
282+
pub mod jn {}
283+
pub mod ldexp {}
284+
pub mod pow {}
285+
pub mod remainder {}
286+
pub mod remquo {}
287+
pub mod scalbn {}
288+
289+
/// x ∈ ℝ
290+
const fn unbounded<F: Float>() -> (Bound<F>, Bound<F>) {
291+
(Bound::Unbounded, Bound::Unbounded)
292+
}
293+
294+
/// x ∈ ℝ >= 0
295+
const fn positive<F: Float>() -> (Bound<F>, Bound<F>) {
296+
(Bound::Included(F::ZERO), Bound::Unbounded)
297+
}
298+
299+
/// x ∈ ℝ > 0
300+
const fn strictly_positive<F: Float>() -> (Bound<F>, Bound<F>) {
301+
(Bound::Excluded(F::ZERO), Bound::Unbounded)
302+
}

crates/libm-test/src/gen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Different generators that can create random or systematic bit patterns.
22
33
use crate::GenerateInput;
4+
pub mod domain;
45
pub mod random;
56

67
/// Helper type to turn any reusable input into a generator.

0 commit comments

Comments
 (0)