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
//! SI prefixes for units. Prefix is just a simple trait, which
//! can be implemented via the `prefix!` macro.
use crateReal;
/// Trait for SI prefixes
///
/// Defines the interface for all prefix types created by the [`crate::prefix!`] macro.
/// Prefixes provide a scaling factor and symbol that can be combined with
/// base units to create scaled versions (like kilogram = kilo + gram).
///
/// This trait is automatically implemented by the [`crate::prefix!`] macro and should
/// not be implemented manually in most cases.
///
/// # Examples
///
/// ```
/// use ferrunitas::{prefix, __model::Prefix};
///
/// prefix!(Kilo, 1000, "k");
/// prefix!(Milli, 0.001, "m");
///
/// // Access prefix properties
/// assert_eq!(Kilo::FACTOR, 1000.0);
/// assert_eq!(Kilo::SYMBOL, "k");
/// assert_eq!(Milli::FACTOR, 0.001);
/// assert_eq!(Milli::SYMBOL, "m");
/// ```
/// Implemented by types that can have SI prefixes
///
/// This marker trait indicates that a unit can be combined with prefixes
/// to create scaled versions. It's used in the `unit!` macro when defining
/// base units with the `prefixable` flag.
///
/// Units marked as prefixable can be used with the `unit!(prefix: ...)` syntax
/// to create prefixed versions automatically.
///
/// # Examples
///
/// ```ruff
/// use ferrunitas::{prefix, unit, system::*, Unit};
/// // In unit definitions:
/// unit!(base: Metre, "m", Length; prefixable); // Metre can have prefixes
/// unit!(prefix: Kilometre, Kilo, Metre); // Creates prefixed version
///
/// // This works because Metre implements Prefixable
/// let km = Kilometre::new(5.0); // 5 kilometres
/// let m = Metre::new(5000.0); // 5000 metres (equivalent)
/// ```
/// Macro to define a prefix with its factor, symbol, and name
///
/// This macro creates SI prefix types that can be used to create prefixed units.
/// A prefix defines a multiplication factor and a symbol that will be combined
/// with base units to create scaled versions (like "kilo" + "metre" = "kilometre").
///
/// Each prefix becomes a zero-sized type that implements the [`Prefix`] trait,
/// storing the conversion factor and symbol as compile-time constants.
///
/// # Arguments
///
/// - `prefix_name`: The identifier for the new prefix type (e.g., `Kilo`, `Milli`)
/// - `factor`: The multiplication factor as a number (e.g., `1000`, `0.001`, `1e-6`)
/// - `symbol`: The prefix symbol as a string literal (e.g., `"k"`, `"m"`, `"μ"`)
///
/// # Examples
///
/// ## Standard SI Prefixes
///
/// ```
/// use ferrunitas::prefix;
///
/// // Large scale prefixes
/// prefix!(Kilo, 1e3, "k"); // 1,000
/// prefix!(Mega, 1e6, "M"); // 1,000,000
/// prefix!(Giga, 1e9, "G"); // 1,000,000,000
/// prefix!(Tera, 1e12, "T"); // 1,000,000,000,000
///
/// // Small scale prefixes
/// prefix!(Milli, 1e-3, "m"); // 0.001
/// prefix!(Micro, 1e-6, "μ"); // 0.000001
/// prefix!(Nano, 1e-9, "n"); // 0.000000001
/// prefix!(Pico, 1e-12, "p"); // 0.000000000001
///
/// // Binary prefixes (used in computing)
/// prefix!(Kibi, 1024, "Ki"); // 2^10
/// prefix!(Mebi, 1048576, "Mi"); // 2^20
/// ```
///
/// ## Custom Prefixes
///
/// ```
/// use ferrunitas::prefix;
///
/// // Custom prefixes for specialized applications
/// prefix!(Dozen, 12, "dz"); // 12 items
/// prefix!(Score, 20, "sc"); // 20 items
/// prefix!(Hundred, 100, "h"); // 100 items
/// prefix!(Gross, 144, "gr"); // 144 items (12 dozen)
///
/// // Fractional custom prefixes
/// prefix!(Half, 0.5, "½"); // Half
/// prefix!(Quarter, 0.25, "¼"); // Quarter
/// ```
///
/// ## Usage with Units
///
/// Once defined, prefixes can be used with the `unit!` macro to create prefixed units:
///
/// ```
/// use ferrunitas::{prefix, unit, quantity, typenum_consts::*};
///
/// // Define a quantity and base unit
/// quantity!(Length: M Z0, L P1, T Z0, I Z0, Th Z0, N Z0, J Z0);
/// unit!(base: Metre, "m", Length; prefixable);
///
/// // Define prefixes
/// prefix!(Kilo, 1000, "k");
/// prefix!(Centi, 0.01, "c");
///
/// // Create prefixed units
/// unit!(prefix: Kilometre, Kilo, Metre); // Creates Kilometre with symbol "km"
/// unit!(prefix: Centimetre, Centi, Metre); // Creates Centimetre with symbol "cm"
/// ```
///
/// # Generated Type
///
/// The macro generates a zero-sized struct that implements [`Prefix`]:
///
/// ```rust
/// use ferrunitas::{Real, __model::Prefix};
/// #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
/// pub struct YourPrefix;
///
/// impl Prefix for YourPrefix {
/// const FACTOR: Real = 1.23; // your factor here
/// const SYMBOL: &'static str = "abc"; // your symbol here
/// }
/// ```