| 1 | /// `libm` cannot have dependencies, so this is vendored directly from the `cfg-if` crate |
| 2 | /// (with some comments stripped for compactness). |
| 3 | macro_rules! cfg_if { |
| 4 | // match if/else chains with a final `else` |
| 5 | ($( |
| 6 | if #[cfg($meta:meta)] { $($tokens:tt)* } |
| 7 | ) else * else { |
| 8 | $($tokens2:tt)* |
| 9 | }) => { |
| 10 | cfg_if! { @__items () ; $( ( ($meta) ($($tokens)*) ), )* ( () ($($tokens2)*) ), } |
| 11 | }; |
| 12 | |
| 13 | // match if/else chains lacking a final `else` |
| 14 | ( |
| 15 | if #[cfg($i_met:meta)] { $($i_tokens:tt)* } |
| 16 | $( else if #[cfg($e_met:meta)] { $($e_tokens:tt)* } )* |
| 17 | ) => { |
| 18 | cfg_if! { |
| 19 | @__items |
| 20 | () ; |
| 21 | ( ($i_met) ($($i_tokens)*) ), |
| 22 | $( ( ($e_met) ($($e_tokens)*) ), )* |
| 23 | ( () () ), |
| 24 | } |
| 25 | }; |
| 26 | |
| 27 | // Internal and recursive macro to emit all the items |
| 28 | // |
| 29 | // Collects all the negated cfgs in a list at the beginning and after the |
| 30 | // semicolon is all the remaining items |
| 31 | (@__items ($($not:meta,)*) ; ) => {}; |
| 32 | (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($tokens:tt)*) ), $($rest:tt)*) => { |
| 33 | #[cfg(all($($m,)* not(any($($not),*))))] cfg_if! { @__identity $($tokens)* } |
| 34 | cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } |
| 35 | }; |
| 36 | |
| 37 | // Internal macro to make __apply work out right for different match types, |
| 38 | // because of how macros matching/expand stuff. |
| 39 | (@__identity $($tokens:tt)*) => { $($tokens)* }; |
| 40 | } |
| 41 | |
| 42 | /// Choose between using an arch-specific implementation and the function body. Returns directly |
| 43 | /// if the arch implementation is used, otherwise continue with the rest of the function. |
| 44 | /// |
| 45 | /// Specify a `use_arch` meta field if an architecture-specific implementation is provided. |
| 46 | /// These live in the `math::arch::some_target_arch` module. |
| 47 | /// |
| 48 | /// Specify a `use_arch_required` meta field if something architecture-specific must be used |
| 49 | /// regardless of feature configuration (`force-soft-floats`). |
| 50 | /// |
| 51 | /// The passed meta options do not need to account for the `arch` target feature. |
| 52 | macro_rules! select_implementation { |
| 53 | ( |
| 54 | name: $fn_name:ident, |
| 55 | // Configuration meta for when to use arch-specific implementation that requires hard |
| 56 | // float ops |
| 57 | $( use_arch: $use_arch:meta, )? |
| 58 | // Configuration meta for when to use the arch module regardless of whether softfloats |
| 59 | // have been requested. |
| 60 | $( use_arch_required: $use_arch_required:meta, )? |
| 61 | args: $($arg:ident),+ , |
| 62 | ) => { |
| 63 | // FIXME: these use paths that are a pretty fragile (`super`). We should figure out |
| 64 | // something better w.r.t. how this is vendored into compiler-builtins. |
| 65 | |
| 66 | // However, we do need a few things from `arch` that are used even with soft floats. |
| 67 | select_implementation! { |
| 68 | @cfg $($use_arch_required)?; |
| 69 | if true { |
| 70 | return super::arch::$fn_name( $($arg),+ ); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | // By default, never use arch-specific implementations if we have force-soft-floats |
| 75 | #[cfg(arch_enabled)] |
| 76 | select_implementation! { |
| 77 | @cfg $($use_arch)?; |
| 78 | // Wrap in `if true` to avoid unused warnings |
| 79 | if true { |
| 80 | return super::arch::$fn_name( $($arg),+ ); |
| 81 | } |
| 82 | } |
| 83 | }; |
| 84 | |
| 85 | // Coalesce helper to construct an expression only if a config is provided |
| 86 | (@cfg ; $ex:expr) => { }; |
| 87 | (@cfg $provided:meta; $ex:expr) => { #[cfg($provided)] $ex }; |
| 88 | } |
| 89 | |
| 90 | /// Construct a 16-bit float from hex float representation (C-style), guaranteed to |
| 91 | /// evaluate at compile time. |
| 92 | #[cfg (f16_enabled)] |
| 93 | #[cfg_attr (feature = "unstable-public-internals" , macro_export)] |
| 94 | #[allow (unused_macros)] |
| 95 | macro_rules! hf16 { |
| 96 | ($s:literal) => {{ |
| 97 | const X: f16 = $crate::support::hf16($s); |
| 98 | X |
| 99 | }}; |
| 100 | } |
| 101 | |
| 102 | /// Construct a 32-bit float from hex float representation (C-style), guaranteed to |
| 103 | /// evaluate at compile time. |
| 104 | #[allow (unused_macros)] |
| 105 | #[cfg_attr (feature = "unstable-public-internals" , macro_export)] |
| 106 | macro_rules! hf32 { |
| 107 | ($s:literal) => {{ |
| 108 | const X: f32 = $crate::support::hf32($s); |
| 109 | X |
| 110 | }}; |
| 111 | } |
| 112 | |
| 113 | /// Construct a 64-bit float from hex float representation (C-style), guaranteed to |
| 114 | /// evaluate at compile time. |
| 115 | #[allow (unused_macros)] |
| 116 | #[cfg_attr (feature = "unstable-public-internals" , macro_export)] |
| 117 | macro_rules! hf64 { |
| 118 | ($s:literal) => {{ |
| 119 | const X: f64 = $crate::support::hf64($s); |
| 120 | X |
| 121 | }}; |
| 122 | } |
| 123 | |
| 124 | /// Construct a 128-bit float from hex float representation (C-style), guaranteed to |
| 125 | /// evaluate at compile time. |
| 126 | #[cfg (f128_enabled)] |
| 127 | #[allow (unused_macros)] |
| 128 | #[cfg_attr (feature = "unstable-public-internals" , macro_export)] |
| 129 | macro_rules! hf128 { |
| 130 | ($s:literal) => {{ |
| 131 | const X: f128 = $crate::support::hf128($s); |
| 132 | X |
| 133 | }}; |
| 134 | } |
| 135 | |
| 136 | /// Assert `F::biteq` with better messages. |
| 137 | #[cfg (test)] |
| 138 | macro_rules! assert_biteq { |
| 139 | ($left:expr, $right:expr, $($tt:tt)*) => {{ |
| 140 | let l = $left; |
| 141 | let r = $right; |
| 142 | let bits = (l.to_bits() - l.to_bits()).leading_zeros(); // hack to get the width from the value |
| 143 | assert!( |
| 144 | l.biteq(r), |
| 145 | "{} \nl: {l:?} ({lb:#0width$x}) \nr: {r:?} ({rb:#0width$x})" , |
| 146 | format_args!($($tt)*), |
| 147 | lb = l.to_bits(), |
| 148 | rb = r.to_bits(), |
| 149 | width = ((bits / 4) + 2) as usize, |
| 150 | |
| 151 | ); |
| 152 | }}; |
| 153 | ($left:expr, $right:expr $(,)?) => { |
| 154 | assert_biteq!($left, $right, "" ) |
| 155 | }; |
| 156 | } |
| 157 | |