Skip to main content

fixed_bigint/
machineword.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Note: in the future, #![feature(const_trait_impl)] should allow
16// turning this into a const trait
17
18pub use crate::const_numtraits::ConstPrimInt;
19use crate::const_numtraits::{
20    ConstBorrowingSub, ConstCarryingAdd, ConstOverflowingAdd, ConstOverflowingSub, ConstToBytes,
21    ConstWideningMul,
22};
23
24c0nst::c0nst! {
25    /// A const-friendly trait for MachineWord operations.
26    /// Extends ConstWideningMul to provide widening multiplication.
27    pub c0nst trait ConstMachineWord:
28        [c0nst] ConstPrimInt +
29        [c0nst] ConstOverflowingAdd +
30        [c0nst] ConstOverflowingSub +
31        [c0nst] ConstCarryingAdd +
32        [c0nst] ConstBorrowingSub +
33        [c0nst] ConstToBytes +
34        [c0nst] ConstWideningMul
35    {
36        type ConstDoubleWord: [c0nst] ConstPrimInt;
37        fn to_double(self) -> Self::ConstDoubleWord;
38        fn from_double(word: Self::ConstDoubleWord) -> Self;
39    }
40
41    impl c0nst ConstMachineWord for u8 {
42        type ConstDoubleWord = u16;
43        fn to_double(self) -> u16 { self as u16 }
44        fn from_double(word: u16) -> u8 { word as u8 }
45    }
46    impl c0nst ConstMachineWord for u16 {
47        type ConstDoubleWord = u32;
48        fn to_double(self) -> u32 { self as u32 }
49        fn from_double(word: u32) -> u16 { word as u16 }
50    }
51    impl c0nst ConstMachineWord for u32 {
52        type ConstDoubleWord = u64;
53        fn to_double(self) -> u64 { self as u64 }
54        fn from_double(word: u64) -> u32 { word as u32 }
55    }
56    impl c0nst ConstMachineWord for u64 {
57        type ConstDoubleWord = u128;
58        fn to_double(self) -> u128 { self as u128 }
59        fn from_double(word: u128) -> u64 { word as u64 }
60    }
61}
62
63/// Represents a CPU native word, from 8-bit to 64-bit, with corresponding
64/// double-word to hold multiplication/division products.
65///
66/// This trait is intentionally sealed via the `ConstMachineWord` supertrait,
67/// as custom implementations are not supported.
68pub trait MachineWord:
69    ConstMachineWord<ConstDoubleWord = Self::DoubleWord> + core::hash::Hash + num_traits::ToPrimitive
70{
71    type DoubleWord: ConstPrimInt;
72}
73
74impl MachineWord for u8 {
75    type DoubleWord = u16;
76}
77impl MachineWord for u16 {
78    type DoubleWord = u32;
79}
80impl MachineWord for u32 {
81    type DoubleWord = u64;
82}
83impl MachineWord for u64 {
84    type DoubleWord = u128;
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    c0nst::c0nst! {
92        pub c0nst fn to_double<T: [c0nst] ConstMachineWord>(a: T) -> T::ConstDoubleWord {
93            a.to_double()
94        }
95    }
96
97    #[test]
98    fn test_constmachineword_ops() {
99        assert_eq!(to_double(200u8), 200u16);
100
101        #[cfg(feature = "nightly")]
102        {
103            const DOUBLE_RES: u16 = to_double(200u8);
104            assert_eq!(DOUBLE_RES, 200u16);
105        }
106    }
107}