he_ring/number_ring/hypercube/
serialization.rs

1use std::marker::PhantomData;
2use std::alloc::Global;
3
4use feanor_math::algorithms::linsolve::LinSolveRing;
5use feanor_math::homomorphism::*;
6use feanor_math::algorithms::convolution::STANDARD_CONVOLUTION;
7use feanor_math::integer::BigIntRingBase;
8use feanor_math::primitive_int::StaticRingBase;
9use feanor_math::ring::*;
10use feanor_math::rings::field::AsFieldBase;
11use feanor_math::rings::local::AsLocalPIR;
12use feanor_math::rings::poly::PolyRing;
13use feanor_math::rings::zn::{FromModulusCreateableZnRing, ZnReductionMap, ZnRing};
14use feanor_math::seq::{VectorFn, VectorView};
15use feanor_math::serialization::*;
16use feanor_math::rings::extension::FreeAlgebraStore;
17use feanor_math::rings::poly::dense_poly::*;
18use serde::de::DeserializeSeed;
19use serde::{Deserialize, Serialize};
20
21use crate::{cyclotomic::*, ZZi64};
22use crate::impl_deserialize_seed_for_dependent_struct;
23use crate::serialization_helper::DeserializeSeedDependentTuple;
24
25use super::isomorphism::{BaseRing, DecoratedBaseRing, HypercubeIsomorphism};
26use super::structure::{HypercubeStructure, HypercubeTypeData};
27
28#[derive(Serialize)]
29#[serde(rename = "HypercubeStructureData")]
30struct SerializableHypercubeStructureData<'a, G: Serialize> {
31    p: SerializableCyclotomicGaloisGroupEl<'a>,
32    d: usize,
33    ms: &'a [usize],
34    gs: G,
35    choice: &'a HypercubeTypeData
36}
37
38impl Serialize for HypercubeStructure {
39
40    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
41        where S: serde::Serializer
42    {
43        SerializableNewtype::new("HypercubeStructure", (&self.galois_group, SerializableHypercubeStructureData {
44            choice: &self.choice,
45            d: self.d,
46            p: SerializableCyclotomicGaloisGroupEl::new(&self.galois_group, self.p),
47            ms: &self.ms,
48            gs: SerializableSeq::new(self.gs.as_fn().map_fn(|g| SerializableCyclotomicGaloisGroupEl::new(&self.galois_group, *g)))
49        })).serialize(serializer)
50    }
51}
52
53struct DeserializeSeedHypercubeStructureData {
54    galois_group: CyclotomicGaloisGroup
55}
56
57fn derive_single_galois_group_deserializer<'a>(deserializer: &'a DeserializeSeedHypercubeStructureData) -> DeserializeSeedCyclotomicGaloisGroupEl<'a> {
58    DeserializeSeedCyclotomicGaloisGroupEl::new(&deserializer.galois_group)
59}
60
61fn derive_multiple_galois_group_deserializer<'de, 'a>(deserializer: &'a DeserializeSeedHypercubeStructureData) -> impl use<'a, 'de> + DeserializeSeed<'de, Value = Vec<CyclotomicGaloisGroupEl>> {
62    DeserializeSeedSeq::new(
63        std::iter::repeat(DeserializeSeedCyclotomicGaloisGroupEl::new(&deserializer.galois_group)),
64        Vec::new(),
65        |mut current, next| { current.push(next); current }
66    )
67}
68
69impl_deserialize_seed_for_dependent_struct!{
70    pub struct HypercubeStructureData<'de> using DeserializeSeedHypercubeStructureData {
71        p: CyclotomicGaloisGroupEl: derive_single_galois_group_deserializer,
72        d: usize: |_| PhantomData,
73        ms: Vec<usize>: |_| PhantomData,
74        gs: Vec<CyclotomicGaloisGroupEl>: derive_multiple_galois_group_deserializer,
75        choice: HypercubeTypeData: |_| PhantomData
76    }
77}
78
79impl<'de> Deserialize<'de> for HypercubeStructure {
80
81    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
82        where D: serde::Deserializer<'de>
83    {
84        let mut deserialized_galois_group = None;
85        DeserializeSeedNewtype::new("HypercubeStructure", DeserializeSeedDependentTuple::new(
86            PhantomData::<CyclotomicGaloisGroup>,
87            |galois_group| {
88                deserialized_galois_group = Some(galois_group);
89                DeserializeSeedHypercubeStructureData { galois_group }
90            }
91        )).deserialize(deserializer).map(|data| {
92            let mut result = HypercubeStructure::new(deserialized_galois_group.take().unwrap(), data.p, data.d, data.ms, data.gs);
93            result.choice = data.choice;
94            return result;
95        })
96    }
97}
98
99#[derive(Serialize)]
100#[serde(rename = "HypercubeIsomorphismData", bound = "")]
101struct SerializableHypercubeIsomorphismData<'a, R>
102    where R: RingStore,
103        R::Type: PolyRing + SerializableElementRing
104{
105    p: i64,
106    e: usize,
107    n: usize,
108    hypercube_structure: &'a HypercubeStructure,
109    slot_ring_moduli: Vec<SerializeOwnedWithRing<R>>
110}
111
112///
113/// Wrapper around a reference to a [`HypercubeIsomorphism`] that
114/// can be used for serialization, without including the ring.
115/// 
116/// This can be deserialized using [`DeserializeSeedHypercubeIsomorphismWithoutRing`]
117/// if the ring is provided during deserialization time.
118/// 
119pub struct SerializableHypercubeIsomorphismWithoutRing<'a, R>
120    where R: RingStore,
121        R::Type: CyclotomicRing,
122        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
123        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
124{
125    hypercube_isomorphism: &'a HypercubeIsomorphism<R>
126}
127
128impl<'a, R> SerializableHypercubeIsomorphismWithoutRing<'a, R>
129    where R: RingStore,
130        R::Type: CyclotomicRing,
131        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
132        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
133{
134    pub fn new(hypercube_isomorphism: &'a HypercubeIsomorphism<R>) -> Self {
135        Self { hypercube_isomorphism }
136    }
137}
138
139impl<'a, R> Serialize for SerializableHypercubeIsomorphismWithoutRing<'a, R>
140    where R: RingStore,
141        R::Type: CyclotomicRing,
142        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
143        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
144{
145    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
146        where S: serde::Serializer
147    {
148        let decorated_base_ring: DecoratedBaseRing<R> = AsLocalPIR::from_zn(RingValue::from(self.hypercube_isomorphism.ring().base_ring().get_ring().clone())).unwrap();
149        let ZpeX = DensePolyRing::new_with(decorated_base_ring, "X", Global, STANDARD_CONVOLUTION);
150        let hom = ZnReductionMap::new(self.hypercube_isomorphism.slot_ring().base_ring(), ZpeX.base_ring()).unwrap();
151        SerializableHypercubeIsomorphismData {
152            p: self.hypercube_isomorphism.p(),
153            e: self.hypercube_isomorphism.e(),
154            n: self.hypercube_isomorphism.hypercube().n(),
155            hypercube_structure: self.hypercube_isomorphism.hypercube(),
156            slot_ring_moduli: (0..self.hypercube_isomorphism.slot_count()).map(|i| 
157                SerializeOwnedWithRing::new(self.hypercube_isomorphism.slot_ring_at(i).generating_poly(&ZpeX, &hom), &ZpeX)
158            ).collect()
159        }.serialize(serializer)
160    }
161}
162struct DeserializeSeedHypercubeIsomorphismData<R>
163    where R: RingStore,
164        R::Type: PolyRing + SerializableElementRing
165{
166    poly_ring: R
167}
168
169fn derive_multiple_poly_deserializer<'de, 'a, R>(deserializer: &'a DeserializeSeedHypercubeIsomorphismData<R>) -> impl use <'a, 'de, R> + DeserializeSeed<'de, Value = Vec<El<R>>>
170    where R: RingStore,
171        R::Type: PolyRing + SerializableElementRing
172{
173    DeserializeSeedSeq::new(
174        std::iter::repeat(DeserializeWithRing::new(&deserializer.poly_ring)),
175        Vec::new(),
176        |mut current, next| { current.push(next); current }
177    )
178}
179
180impl_deserialize_seed_for_dependent_struct!{
181    <{'de, R}> pub struct HypercubeIsomorphismData<{'de, R}> using DeserializeSeedHypercubeIsomorphismData<R> {
182        p: i64: |_| PhantomData,
183        e: usize: |_| PhantomData,
184        n: usize: |_| PhantomData,
185        hypercube_structure: HypercubeStructure: |_| PhantomData,
186        slot_ring_moduli: Vec<El<R>>: derive_multiple_poly_deserializer
187    } where R: RingStore, R::Type: PolyRing + SerializableElementRing
188}
189
190///
191/// A [`DeserializeSeed`] to deserialize a [`HypercubeIsomorphism`]
192/// that has been serialized without the ring. Hence, for deserialization,
193/// it is necessary that the ring is provided again. Therefore, we must
194/// use a [`DeserializeSeed`] wrapping the ring, i.e. this struct.
195/// 
196pub struct DeserializeSeedHypercubeIsomorphismWithoutRing<R>
197    where R: RingStore,
198        R::Type: CyclotomicRing,
199        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
200        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
201{
202    ring: R
203}
204
205impl<R> DeserializeSeedHypercubeIsomorphismWithoutRing<R>
206    where R: RingStore,
207        R::Type: CyclotomicRing,
208        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
209        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
210{
211    pub fn new(ring: R) -> Self {
212        Self { ring }
213    }
214}
215
216impl<'de, R> DeserializeSeed<'de> for DeserializeSeedHypercubeIsomorphismWithoutRing<R>
217    where R: RingStore,
218        R::Type: CyclotomicRing,
219        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
220        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
221{
222    type Value = HypercubeIsomorphism<R>;
223
224    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
225        where D: serde::Deserializer<'de>
226    {
227        let decorated_base_ring: DecoratedBaseRing<R> = AsLocalPIR::from_zn(RingValue::from(self.ring.base_ring().get_ring().clone())).unwrap();
228        let ZpeX = DensePolyRing::new_with(decorated_base_ring, "X", Global, STANDARD_CONVOLUTION);
229        let deserialized = DeserializeSeedHypercubeIsomorphismData { poly_ring: &ZpeX }.deserialize(deserializer)?;
230        assert_eq!(self.ring.n(), deserialized.n);
231        assert_eq!(self.ring.characteristic(ZZi64).unwrap(), ZZi64.pow(deserialized.p, deserialized.e));
232        let hypercube_structure = deserialized.hypercube_structure;
233        let slot_ring_moduli = deserialized.slot_ring_moduli;
234        let result = HypercubeIsomorphism::create::<false>(
235            self.ring,
236            hypercube_structure,
237            ZpeX,
238            slot_ring_moduli
239        );
240        return Ok(result);
241    }
242}
243
244impl<R> Serialize for HypercubeIsomorphism<R>
245    where R: RingStore + Serialize,
246        R::Type: CyclotomicRing,
247        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
248        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
249{
250    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
251        where S: serde::Serializer
252    {
253        SerializableNewtype::new("HypercubeIsomorphism", (self.ring(), SerializableHypercubeIsomorphismWithoutRing::new(self))).serialize(serializer)
254    }
255}
256
257impl<'de, R> Deserialize<'de> for HypercubeIsomorphism<R>
258    where R: RingStore + Deserialize<'de>,
259        R::Type: CyclotomicRing,
260        BaseRing<R>: Clone + ZnRing + CanHomFrom<StaticRingBase<i64>> + CanHomFrom<BigIntRingBase> + LinSolveRing + FromModulusCreateableZnRing + SerializableElementRing,
261        AsFieldBase<DecoratedBaseRing<R>>: CanIsoFromTo<<DecoratedBaseRing<R> as RingStore>::Type> + SelfIso
262{
263    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
264        where D: serde::Deserializer<'de>
265    {
266        DeserializeSeedNewtype::new("HypercubeIsomorphism", DeserializeSeedDependentTuple::new(
267            PhantomData::<R>,
268            |ring| DeserializeSeedHypercubeIsomorphismWithoutRing::new(ring)
269        )).deserialize(deserializer)
270    }
271}