Sun, 18 May 2025 23:15:50 -0500
Basic Pair pyo3 conversions
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
1 | /*! |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
2 | Arithmetic of [`Mapping`]s. |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
3 | */ |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
4 | |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
5 | use crate::instance::{Instance, Space}; |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
6 | use crate::mapping::{DifferentiableImpl, DifferentiableMapping, Mapping}; |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
7 | use crate::types::*; |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
8 | use serde::Serialize; |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
9 | |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
10 | /// A trait for encoding constant [`Float`] values |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
11 | pub trait Constant: Copy + Sync + Send + 'static + std::fmt::Debug + Into<Self::Type> { |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
12 | /// The type of the value |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
13 | type Type: Float; |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
14 | /// Returns the value of the constant |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
15 | fn value(&self) -> Self::Type; |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
16 | } |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
17 | |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
18 | impl<F: Float> Constant for F { |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
19 | type Type = F; |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
20 | #[inline] |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
21 | fn value(&self) -> F { |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
22 | *self |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
23 | } |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
24 | } |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
25 | |
|
75
e9f4550cfa18
Fix out-of-date references in doc comments
Tuomo Valkonen <tuomov@iki.fi>
parents:
69
diff
changeset
|
26 | /// Weighting of a [`Mapping`] by scalar multiplication. |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
27 | #[derive(Copy, Clone, Debug, Serialize)] |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
28 | pub struct Weighted<T, C: Constant> { |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
29 | /// The weight |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
30 | pub weight: C, |
|
75
e9f4550cfa18
Fix out-of-date references in doc comments
Tuomo Valkonen <tuomov@iki.fi>
parents:
69
diff
changeset
|
31 | /// The base [`Mapping`] being weighted. |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
32 | pub base_fn: T, |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
33 | } |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
34 | |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
35 | impl<T, C> Weighted<T, C> |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
36 | where |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
37 | C: Constant, |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
38 | { |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
39 | /// Construct from an iterator. |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
40 | pub fn new(weight: C, base_fn: T) -> Self { |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
41 | Weighted { weight, base_fn } |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
42 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
43 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
44 | |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
45 | impl<'a, T, V, D, F, C> Mapping<D> for Weighted<T, C> |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
46 | where |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
47 | F: Float, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
48 | D: Space, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
49 | T: Mapping<D, Codomain = V>, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
50 | V: Space + ClosedMul<F>, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
51 | C: Constant<Type = F>, |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
52 | { |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
53 | type Codomain = V; |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
54 | |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
55 | #[inline] |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
56 | fn apply<I: Instance<D>>(&self, x: I) -> Self::Codomain { |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
57 | self.base_fn.apply(x) * self.weight.value() |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
58 | } |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
59 | } |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
60 | |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
61 | impl<'a, T, V, D, F, C> DifferentiableImpl<D> for Weighted<T, C> |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
62 | where |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
63 | F: Float, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
64 | D: Space, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
65 | T: DifferentiableMapping<D, DerivativeDomain = V>, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
66 | V: Space + std::ops::Mul<F, Output = V>, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
67 | C: Constant<Type = F>, |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
68 | { |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
69 | type Derivative = V; |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
70 | |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
71 | #[inline] |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
72 | fn differential_impl<I: Instance<D>>(&self, x: I) -> Self::Derivative { |
|
68
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
73 | self.base_fn.differential(x) * self.weight.value() |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
74 | } |
|
c5f70e767511
Split out and generalise Weighted
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
75 | } |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
76 | |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
77 | /// A sum of [`Mapping`]s. |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
78 | #[derive(Serialize, Debug, Clone)] |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
79 | pub struct MappingSum<M>(Vec<M>); |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
80 | |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
81 | impl<M> MappingSum<M> { |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
82 | /// Construct from an iterator. |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
83 | pub fn new<I: IntoIterator<Item = M>>(iter: I) -> Self { |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
84 | MappingSum(iter.into_iter().collect()) |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
85 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
86 | |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
87 | /// Iterate over the component functions of the sum |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
88 | pub fn iter(&self) -> std::slice::Iter<'_, M> { |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
89 | self.0.iter() |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
90 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
91 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
92 | |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
93 | impl<Domain, M> Mapping<Domain> for MappingSum<M> |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
94 | where |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
95 | Domain: Space + Clone, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
96 | M: Mapping<Domain>, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
97 | M::Codomain: std::iter::Sum + Clone, |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
98 | { |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
99 | type Codomain = M::Codomain; |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
100 | |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
101 | fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
|
133
2b13f8a0c8ba
Replace Instance ref_instance and decompose by eval_* for flexibility
Tuomo Valkonen <tuomov@iki.fi>
parents:
128
diff
changeset
|
102 | x.eval_ref_decompose(|xr| self.0.iter().map(|c| c.apply(xr)).sum()) |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
103 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
104 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
105 | |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
106 | impl<Domain, M> DifferentiableImpl<Domain> for MappingSum<M> |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
107 | where |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
108 | Domain: Space, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
109 | M: DifferentiableMapping<Domain>, |
|
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
110 | M::DerivativeDomain: std::iter::Sum, |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
111 | { |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
112 | type Derivative = M::DerivativeDomain; |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
113 | |
|
128
f75bf34adda0
Switch from Cow to MyCow for DifferentiableImpl to avoid Clone trait bound
Tuomo Valkonen <tuomov@iki.fi>
parents:
75
diff
changeset
|
114 | fn differential_impl<I: Instance<Domain>>(&self, x: I) -> Self::Derivative { |
|
133
2b13f8a0c8ba
Replace Instance ref_instance and decompose by eval_* for flexibility
Tuomo Valkonen <tuomov@iki.fi>
parents:
128
diff
changeset
|
115 | x.eval_ref_decompose(|xr| self.0.iter().map(|c| c.differential(xr)).sum()) |
|
69
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
116 | } |
|
e5fab0125a8e
Move Sum to operator_arithmetic as MappingSum
Tuomo Valkonen <tuomov@iki.fi>
parents:
68
diff
changeset
|
117 | } |