1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//! Momentum (base unit kilogram meter per second, kg · m · s⁻¹).

quantity! {
    /// Momentum (base unit kilogram meter per second, kg · m · s⁻¹).
    quantity: Momentum; "momentum";
    /// Dimension of momentum, LMT⁻¹ (base unit kilogram meter per second, kg · m · s⁻¹).
    dimension: ISQ<
        P1,     // length
        P1,     // mass
        N1,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottagram_meter_per_second: prefix!(yotta) / prefix!(kilo); "Yg · m/s",
            "yottagram meter per second", "yottagram meters per second";
        @zettagram_meter_per_second: prefix!(zetta) / prefix!(kilo); "Zg · m/s",
            "zettagram meter per second", "zettagram meters per second";
        @exagram_meter_per_second: prefix!(exa) / prefix!(kilo); "Eg · m/s",
            "exagram meter per second", "exagram meters per second";
        @petagram_meter_per_second: prefix!(peta) / prefix!(kilo); "Pg · m/s",
            "petagram meter per second", "petagram meters per second";
        @teragram_meter_per_second: prefix!(tera) / prefix!(kilo); "Tg · m/s",
            "teragram meter per second", "teragram meters per second";
        @gigagram_meter_per_second: prefix!(giga) / prefix!(kilo); "Gg · m/s",
            "gigagram meter per second", "gigagram meters per second";
        @megagram_meter_per_second: prefix!(mega) / prefix!(kilo); "Mg · m/s",
            "megagram meter per second", "megagram meters per second";
        /// Derived unit of momentum.
        @kilogram_meter_per_second: prefix!(kilo) / prefix!(kilo); "kg · m/s",
            "kilogram meter per second", "kilogram meters per second";
        @hectogram_meter_per_second: prefix!(hecto) / prefix!(kilo); "hg · m/s",
            "hectogram meter per second", "hectogram meters per second";
        @decagram_meter_per_second: prefix!(deca) / prefix!(kilo); "dag · m/s",
            "decagram meter per second", "decagram meters per second";
        @gram_meter_per_second: prefix!(none) / prefix!(kilo); "g · m/s", "gram meter per second",
            "gram meters per second";
        @decigram_meter_per_second: prefix!(deci) / prefix!(kilo); "dg · m/s",
            "decigram meter per second", "decigram meters per second";
        @centigram_meter_per_second: prefix!(centi) / prefix!(kilo); "cg · m/s",
            "centigram meter per second", "centigram meters per second";
        @milligram_meter_per_second: prefix!(milli) / prefix!(kilo); "mg · m/s",
            "milligram meter per second", "milligram meters per second";
        @microgram_meter_per_second: prefix!(micro) / prefix!(kilo); "µg · m/s",
            "microgram meter per second", "microgram meters per second";
        @nanogram_meter_per_second: prefix!(nano) / prefix!(kilo); "ng · m/s",
            "nanogram meter per second", "nanogram meters per second";
        @picogram_meter_per_second: prefix!(pico) / prefix!(kilo); "pg · m/s",
            "picogram meter per second", "picogram meters per second";
        @femtogram_meter_per_second: prefix!(femto) / prefix!(kilo); "fg · m/s",
            "femtogram meter per second", "femtogram meters per second";
        @attogram_meter_per_second: prefix!(atto) / prefix!(kilo); "ag · m/s",
            "attogram meter per second", "attogram meters per second";
        @zeptogram_meter_per_second: prefix!(zepto) / prefix!(kilo); "zg · m/s",
            "zeptogram meter per second", "zeptogram meters per second";
        @yoctogram_meter_per_second: prefix!(yocto) / prefix!(kilo); "yg · m/s",
            "yoctogram meter per second", "yoctogram meters per second";

        @kilogram_yottameter_per_second: prefix!(yotta); "kg · Ym/s",
            "kilogram yottameter per second", "kilogram yottameters per second";
        @kilogram_zettameter_per_second: prefix!(zetta); "kg · Zm/s",
            "kilogram zettameter per second", "kilogram zettameters per second";
        @kilogram_exameter_per_second: prefix!(exa); "kg · Em/s", "kilogram exameter per second",
            "kilogram exameters per second";
        @kilogram_petameter_per_second: prefix!(peta); "kg · Pm/s", "kilogram petameter per second",
            "kilogram petameters per second";
        @kilogram_terameter_per_second: prefix!(tera); "kg · Tm/s", "kilogram terameter per second",
            "kilogram terameters per second";
        @kilogram_gigameter_per_second: prefix!(giga); "kg · Gm/s", "kilogram gigameter per second",
            "kilogram gigameters per second";
        @kilogram_megameter_per_second: prefix!(mega); "kg · Mm/s", "kilogram megameter per second",
            "kilogram megameters per second";
        @kilogram_kilometer_per_second: prefix!(kilo); "kg · km/s", "kilogram kilometer per second",
            "kilogram kilometers per second";
        @kilogram_hectometer_per_second: prefix!(hecto); "kg · hm/s",
            "kilogram hectometer per second", "kilogram hectometers per second";
        @kilogram_decameter_per_second: prefix!(deca); "kg · dam/s",
            "kilogram decameter per second", "kilogram decameters per second";
        @kilogram_decimeter_per_second: prefix!(deci); "kg · dm/s", "kilogram decimeter per second",
            "kilogram decimeters per second";
        @kilogram_centimeter_per_second: prefix!(centi); "kg · cm/s",
            "kilogram centimeter per second", "kilogram centimeters per second";
        @kilogram_millimeter_per_second: prefix!(milli); "kg · mm/s",
            "kilogram millimeter per second", "kilogram millimeters per second";
        @kilogram_micrometer_per_second: prefix!(micro); "kg · µm/s",
            "kilogram micrometer per second", "kilogram micrometers per second";
        @kilogram_nanometer_per_second: prefix!(nano); "kg · nm/s", "kilogram nanometer per second",
            "kilogram nanometers per second";
        @kilogram_picometer_per_second: prefix!(pico); "kg · pm/s", "kilogram picometer per second",
            "kilogram picometers per second";
        @kilogram_femtometer_per_second: prefix!(femto); "kg · fm/s",
            "kilogram femtometer per second", "kilogram femtometers per second";
        @kilogram_attometer_per_second: prefix!(atto); "kg · am/s", "kilogram attometer per second",
            "kilogram attometers per second";
        @kilogram_zeptometer_per_second: prefix!(zepto); "kg · zm/s",
            "kilogram zeptometer per second", "kilogram zeptometers per second";
        @kilogram_yoctometer_per_second: prefix!(yocto); "kg · ym/s",
            "kilogram yoctometer per second", "kilogram yoctometers per second";

        @ton_meter_per_second: prefix!(mega) / prefix!(kilo); "t · m/s", "ton meter per second",
            "ton meters per second";

        @kilogram_meter_per_minute: 1.666_666_666_666_666_6_E-2; "kg · m/min",
            "kilogram meter per minute", "kilogram meters per minute";
        @kilogram_meter_per_hour: 2.777_777_777_777_777_7_E-4; "kg · m/h",
            "kilogram meter per hour", "kilogram meters per hour";
        @kilogram_meter_per_day: 1.157_407_407_407_407_4_E-5; "kg · m/d", "kilogram meter per day",
            "kilogram meters per day";

        @slug_foot_per_second: 4.448_220_72_E0; "slug · ft/s", "slug foot per second",
            "slug feet per second";
        @slug_inch_per_second: 3.706_850_6_E-1; "slug · in/s", "slug inch per second",
            "slug inches per second";
        @pound_foot_per_second: 1.382_549_635_2_E-1; "lb · ft/s", "pound foot per second",
            "pound feet per second";
        @pound_inch_per_second: 1.152_124_696_E-2; "lb · in/s", "pound inch per second",
            "pound inches per second";
    }
}

#[cfg(test)]
mod test {
    storage_types! {
        use crate::num::One;
        use crate::si::length as l;
        use crate::si::mass as m;
        use crate::si::momentum as mmm;
        use crate::si::quantities::*;
        use crate::si::time as t;
        use crate::tests::Test;

        #[test]
        fn check_dimension() {
            let _: Momentum<V> = Mass::new::<m::kilogram>(V::one())
                * Length::new::<l::meter>(V::one())
                / Time::new::<t::second>(V::one());
        }

        #[test]
        fn check_units() {
            test::<m::yottagram, l::meter, t::second, mmm::yottagram_meter_per_second>();
            test::<m::zettagram, l::meter, t::second, mmm::zettagram_meter_per_second>();
            test::<m::exagram, l::meter, t::second, mmm::exagram_meter_per_second>();
            test::<m::petagram, l::meter, t::second, mmm::petagram_meter_per_second>();
            test::<m::teragram, l::meter, t::second, mmm::teragram_meter_per_second>();
            test::<m::gigagram, l::meter, t::second, mmm::gigagram_meter_per_second>();
            test::<m::megagram, l::meter, t::second, mmm::megagram_meter_per_second>();
            test::<m::kilogram, l::meter, t::second, mmm::kilogram_meter_per_second>();
            test::<m::hectogram, l::meter, t::second, mmm::hectogram_meter_per_second>();
            test::<m::decagram, l::meter, t::second, mmm::decagram_meter_per_second>();
            test::<m::gram, l::meter, t::second, mmm::gram_meter_per_second>();
            test::<m::decigram, l::meter, t::second, mmm::decigram_meter_per_second>();
            test::<m::centigram, l::meter, t::second, mmm::centigram_meter_per_second>();
            test::<m::milligram, l::meter, t::second, mmm::milligram_meter_per_second>();
            test::<m::microgram, l::meter, t::second, mmm::microgram_meter_per_second>();
            test::<m::nanogram, l::meter, t::second, mmm::nanogram_meter_per_second>();
            test::<m::picogram, l::meter, t::second, mmm::picogram_meter_per_second>();
            test::<m::femtogram, l::meter, t::second, mmm::femtogram_meter_per_second>();
            test::<m::attogram, l::meter, t::second, mmm::attogram_meter_per_second>();
            test::<m::zeptogram, l::meter, t::second, mmm::zeptogram_meter_per_second>();
            test::<m::yoctogram, l::meter, t::second, mmm::yoctogram_meter_per_second>();

            test::<m::kilogram, l::yottameter, t::second, mmm::kilogram_yottameter_per_second>();
            test::<m::kilogram, l::zettameter, t::second, mmm::kilogram_zettameter_per_second>();
            test::<m::kilogram, l::exameter, t::second, mmm::kilogram_exameter_per_second>();
            test::<m::kilogram, l::petameter, t::second, mmm::kilogram_petameter_per_second>();
            test::<m::kilogram, l::terameter, t::second, mmm::kilogram_terameter_per_second>();
            test::<m::kilogram, l::gigameter, t::second, mmm::kilogram_gigameter_per_second>();
            test::<m::kilogram, l::megameter, t::second, mmm::kilogram_megameter_per_second>();
            test::<m::kilogram, l::kilometer, t::second, mmm::kilogram_kilometer_per_second>();
            test::<m::kilogram, l::hectometer, t::second, mmm::kilogram_hectometer_per_second>();
            test::<m::kilogram, l::decameter, t::second, mmm::kilogram_decameter_per_second>();
            test::<m::kilogram, l::decimeter, t::second, mmm::kilogram_decimeter_per_second>();
            test::<m::kilogram, l::centimeter, t::second, mmm::kilogram_centimeter_per_second>();
            test::<m::kilogram, l::millimeter, t::second, mmm::kilogram_millimeter_per_second>();
            test::<m::kilogram, l::micrometer, t::second, mmm::kilogram_micrometer_per_second>();
            test::<m::kilogram, l::nanometer, t::second, mmm::kilogram_nanometer_per_second>();
            test::<m::kilogram, l::picometer, t::second, mmm::kilogram_picometer_per_second>();
            test::<m::kilogram, l::femtometer, t::second, mmm::kilogram_femtometer_per_second>();
            test::<m::kilogram, l::attometer, t::second, mmm::kilogram_attometer_per_second>();
            test::<m::kilogram, l::zeptometer, t::second, mmm::kilogram_zeptometer_per_second>();
            test::<m::kilogram, l::yoctometer, t::second, mmm::kilogram_yoctometer_per_second>();

            test::<m::ton, l::meter, t::second, mmm::ton_meter_per_second>();
            test::<m::kilogram, l::meter, t::minute, mmm::kilogram_meter_per_minute>();
            test::<m::kilogram, l::meter, t::hour, mmm::kilogram_meter_per_hour>();
            test::<m::kilogram, l::meter, t::day, mmm::kilogram_meter_per_day>();

            test::<m::slug, l::foot, t::second, mmm::slug_foot_per_second>();
            test::<m::slug, l::inch, t::second, mmm::slug_inch_per_second>();
            test::<m::pound, l::foot, t::second, mmm::pound_foot_per_second>();
            test::<m::pound, l::inch, t::second, mmm::pound_inch_per_second>();

            fn test<M, L, T, R>()
            where
                M: m::Conversion<V>,
                L: l::Conversion<V>,
                T: t::Conversion<V>,
                R: mmm::Conversion<V>
            {
                Test::assert_approx_eq(&Momentum::new::<R>(V::one()),
                    &(Mass::new::<M>(V::one()) * Length::new::<L>(V::one())
                        / Time::new::<T>(V::one())));
            }
        }
    }
}