Skip to content

Commit a803cb3

Browse files
committed
Add f32::from(int) and f64::from(int) when they are lossless
Part of #221.
1 parent f07048c commit a803cb3

File tree

3 files changed

+127
-7
lines changed

3 files changed

+127
-7
lines changed

sus/num/__private/float_methods.inc

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,17 @@ constexpr inline _self(P v) noexcept : primitive_value(v) {}
147147
/// #[doc.overloads=from.float]
148148
template <Float F>
149149
requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<_primitive>())
150-
sus_pure static constexpr _self from(F f) noexcept {
151-
return _self(f);
150+
sus_pure static constexpr _self from(F v) noexcept {
151+
return _self(v);
152152
}
153153

154154
/// Construction from primitive floating point types where no bits are lost.
155155
///
156-
/// #[doc.overloads=from.primitivefloat]
157-
template <PrimitiveFloat F>
158-
requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<_primitive>())
159-
sus_pure static constexpr _self from(F f) noexcept {
160-
return _self(f);
156+
/// #[doc.overloads=from.primitive_float]
157+
template <PrimitiveFloat P>
158+
requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<_primitive>())
159+
sus_pure static constexpr _self from(P v) noexcept {
160+
return _self(v);
161161
}
162162

163163
/// Assignment from floating point types where no bits are lost.
@@ -180,6 +180,32 @@ constexpr inline _self& operator=(P v) noexcept {
180180
return *this;
181181
}
182182

183+
/// Construction from integer types where no bits are lost.
184+
///
185+
/// For [`f32`]($sus::num::f32) this includes integer types up to 16 bits.
186+
/// For [`f64`]($sus::num::f64) this includes integer types up to 32 bits.
187+
///
188+
/// #[doc.overloads=from.int]
189+
template <Integer I>
190+
requires(::sus::mem::size_of<I>() * 8 <=
191+
__private::num_mantissa_digits<_primitive>())
192+
sus_pure static constexpr _self from(I v) noexcept {
193+
return _self(static_cast<_primitive>(v.primitive_value));
194+
}
195+
196+
/// Construction from integer types where no bits are lost.
197+
///
198+
/// For [`f32`]($sus::num::f32) this includes integer types up to 16 bits.
199+
/// For [`f64`]($sus::num::f64) this includes integer types up to 32 bits.
200+
///
201+
/// #[doc.overloads=from.primitive_int]
202+
template <PrimitiveInteger P>
203+
requires(::sus::mem::size_of<P>() * 8 <=
204+
__private::num_mantissa_digits<_primitive>())
205+
sus_pure static constexpr _self from(P v) noexcept {
206+
return _self(static_cast<_primitive>(v));
207+
}
208+
183209
/// Constructs a [`@doc.self `]($sus::num::@doc.self) from an
184210
/// [`Iterator`]($sus::iter::Iterator) by computing the sum of all elements in
185211
/// the iterator.

sus/num/f32_unittest.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,47 @@ TEST(f32, ToPrimitive) {
228228
static_assert(NotConvertible<f32, size_t>);
229229
}
230230

231+
TEST(f32, From) {
232+
static_assert(sus::construct::From<f32, bool>);
233+
static_assert(sus::construct::From<f32, char>);
234+
static_assert(sus::construct::From<f32, unsigned char>);
235+
static_assert(sus::construct::From<f32, signed char>);
236+
static_assert(sus::construct::From<f32, int8_t>);
237+
static_assert(sus::construct::From<f32, int16_t>);
238+
static_assert(!sus::construct::From<f32, int32_t>);
239+
static_assert(!sus::construct::From<f32, int64_t>);
240+
static_assert(sus::construct::From<f32, uint8_t>);
241+
static_assert(sus::construct::From<f32, uint16_t>);
242+
static_assert(!sus::construct::From<f32, uint32_t>);
243+
static_assert(!sus::construct::From<f32, uint64_t>);
244+
static_assert(!sus::construct::From<f32, size_t>);
245+
static_assert(!sus::construct::From<f32, uintptr_t>);
246+
247+
static_assert(sus::construct::From<f32, i8>);
248+
static_assert(sus::construct::From<f32, i16>);
249+
static_assert(!sus::construct::From<f32, i32>);
250+
static_assert(!sus::construct::From<f32, i64>);
251+
static_assert(!sus::construct::From<f32, isize>);
252+
static_assert(sus::construct::From<f32, u8>);
253+
static_assert(sus::construct::From<f32, u16>);
254+
static_assert(!sus::construct::From<f32, u32>);
255+
static_assert(!sus::construct::From<f32, u64>);
256+
static_assert(!sus::construct::From<f32, usize>);
257+
static_assert(!sus::construct::From<f32, uptr>);
258+
259+
static_assert(f32::from(true) == 1_f32);
260+
static_assert(f32::from(int16_t{-33}) == -33_f32);
261+
static_assert(f32::from(-33_i16) == -33_f32);
262+
static_assert(f32::from(int16_t{33}) == 33_f32);
263+
static_assert(f32::from(33_u16) == 33_f32);
264+
265+
EXPECT_EQ(f32::from(true), 1_f32);
266+
EXPECT_EQ(f32::from(int16_t{-33}), -33_f32);
267+
EXPECT_EQ(f32::from(-33_i16), -33_f32);
268+
EXPECT_EQ(f32::from(int16_t{33}), 33_f32);
269+
EXPECT_EQ(f32::from(33_u16), 33_f32);
270+
}
271+
231272
TEST(f32, Negate) {
232273
constexpr auto a = -(0.345_f32);
233274
EXPECT_EQ(a, f32(-0.345f));

sus/num/f64_unittest.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,59 @@ TEST(f64, ToPrimitive) {
228228
static_assert(NotConvertible<f64, size_t>);
229229
}
230230

231+
TEST(f64, From) {
232+
static_assert(sus::construct::From<f64, bool>);
233+
static_assert(sus::construct::From<f64, char>);
234+
static_assert(sus::construct::From<f64, unsigned char>);
235+
static_assert(sus::construct::From<f64, signed char>);
236+
static_assert(sus::construct::From<f64, int8_t>);
237+
static_assert(sus::construct::From<f64, int16_t>);
238+
static_assert(sus::construct::From<f64, int32_t>);
239+
static_assert(!sus::construct::From<f64, int64_t>);
240+
static_assert(sus::construct::From<f64, uint8_t>);
241+
static_assert(sus::construct::From<f64, uint16_t>);
242+
static_assert(sus::construct::From<f64, uint32_t>);
243+
static_assert(!sus::construct::From<f64, uint64_t>);
244+
static_assert((sizeof(size_t) <= sizeof(u32)) ==
245+
sus::construct::From<f64, size_t>);
246+
static_assert((sizeof(uintptr_t) <= sizeof(u32)) ==
247+
sus::construct::From<f64, uintptr_t>);
248+
249+
static_assert(sus::construct::From<f64, i8>);
250+
static_assert(sus::construct::From<f64, i16>);
251+
static_assert(sus::construct::From<f64, i32>);
252+
static_assert(!sus::construct::From<f64, i64>);
253+
static_assert(!sus::construct::From<f64, isize>);
254+
static_assert(sus::construct::From<f64, u8>);
255+
static_assert(sus::construct::From<f64, u16>);
256+
static_assert(sus::construct::From<f64, u32>);
257+
static_assert(!sus::construct::From<f64, u64>);
258+
static_assert((sizeof(usize) <= sizeof(u32)) ==
259+
sus::construct::From<f64, usize>);
260+
static_assert((sizeof(uptr) <= sizeof(u32)) ==
261+
sus::construct::From<f64, uptr>);
262+
263+
static_assert(f64::from(true) == 1_f64);
264+
static_assert(f64::from(int16_t{-33}) == -33_f64);
265+
static_assert(f64::from(-33_i16) == -33_f64);
266+
static_assert(f64::from(int16_t{33}) == 33_f64);
267+
static_assert(f64::from(33_u16) == 33_f64);
268+
static_assert(f64::from(int32_t{-33}) == -33_f64);
269+
static_assert(f64::from(-33_i32) == -33_f64);
270+
static_assert(f64::from(int32_t{33}) == 33_f64);
271+
static_assert(f64::from(33_u32) == 33_f64);
272+
273+
EXPECT_EQ(f64::from(true), 1_f64);
274+
EXPECT_EQ(f64::from(int16_t{-33}), -33_f64);
275+
EXPECT_EQ(f64::from(-33_i16), -33_f64);
276+
EXPECT_EQ(f64::from(int16_t{33}), 33_f64);
277+
EXPECT_EQ(f64::from(33_u16), 33_f64);
278+
EXPECT_EQ(f64::from(int32_t{-33}), -33_f64);
279+
EXPECT_EQ(f64::from(-33_i32), -33_f64);
280+
EXPECT_EQ(f64::from(int32_t{33}), 33_f64);
281+
EXPECT_EQ(f64::from(33_u32), 33_f64);
282+
}
283+
231284
TEST(f64, Negate) {
232285
constexpr auto a = -(0.345_f64);
233286
EXPECT_EQ(a, f64(-0.345));

0 commit comments

Comments
 (0)