spreadsheet_ods_formula/
math.rs

1//!
2//! Mathematical functions.
3//!
4
5pub use crate::generated::math::*;
6
7use crate::{Any, Criterion, FnNumberVar, Reference};
8use std::fmt::Write;
9
10/// Parameter for CONVERT().
11#[derive(Debug)]
12pub enum BaseUnit {
13    UKAcre,
14    USAcre,
15    SqAngstrom,
16    Ar,
17    SqFoot,
18    Hectare,
19    SqInch,
20    SqMeter,
21    Morgen,
22    SqMile,
23    SqNauticalMile,
24    SqPica,
25    SqYard,
26    Angstrom,
27    Ell,
28    Foot,
29    Inch,
30    LightYear,
31    Meter,
32    Mile,
33    NauticalMile,
34    Parsec,
35    Pica,
36    SurveyMile,
37    Yard,
38    BTU,
39    ThermCalorie,
40    ITCalorie,
41    Erg,
42    ElectronVolt,
43    Flb,
44    HPh,
45    Joule,
46    WattHour,
47    Dyne,
48    Newton,
49    Lbf,
50    Pond,
51    Bit,
52    Byte,
53    Gauss,
54    Tesla,
55    Gram,
56    Grain,
57    Cwt,
58    UKCwt,
59    Lbm,
60    Stone,
61    Ton,
62    Ozm,
63    Sg,
64    AtomicMassUnit,
65    UKTon,
66    HP,
67    PS,
68    Watt,
69    Atm,
70    MmHg,
71    Pascal,
72    Psi,
73    Torr,
74    AdmiralityKnot,
75    Knot,
76    MetersPerHour,
77    MetersPerSecond,
78    MilesPerHour,
79    Celsius,
80    Fahrenheit,
81    Kelvin,
82    Rankine,
83    Reaumur,
84    Day,
85    Hour,
86    Minute,
87    Second,
88    Year,
89    CbAngstrom,
90    Barrel,
91    Bushel,
92    Cup,
93    CbFoot,
94    Gallon,
95    GRT,
96    CbInch,
97    Liter,
98    CbLightYear,
99    CbMeter,
100    CbMile,
101    MTon,
102    CbNauticalMile,
103    FluidOunce,
104    CbPica,
105    Pint,
106    Quart,
107    Tablespoon,
108    Teaspoon,
109    ModernTeaspoon,
110    UKGallon,
111    UKPint,
112    UKQuart,
113    CbYard,
114}
115
116impl Any for BaseUnit {
117    fn formula(&self, buf: &mut String) {
118        buf.push_str(match self {
119            BaseUnit::UKAcre => "uk_acre",
120            BaseUnit::USAcre => "us_acre",
121            BaseUnit::SqAngstrom => "ang2",
122            BaseUnit::Ar => "ar",
123            BaseUnit::SqFoot => "ft2",
124            BaseUnit::Hectare => "ha",
125            BaseUnit::SqInch => "in2",
126            BaseUnit::SqMeter => "ly2",
127            BaseUnit::Morgen => "Morgen",
128            BaseUnit::SqMile => "mi2",
129            BaseUnit::SqNauticalMile => "Nmi2",
130            BaseUnit::SqPica => "Pica2",
131            BaseUnit::SqYard => "yd2",
132            BaseUnit::Angstrom => "ang",
133            BaseUnit::Ell => "ell",
134            BaseUnit::Foot => "ft",
135            BaseUnit::Inch => "in",
136            BaseUnit::LightYear => "ly",
137            BaseUnit::Meter => "m",
138            BaseUnit::Mile => "mi",
139            BaseUnit::NauticalMile => "Nmi",
140            BaseUnit::Parsec => "pc",
141            BaseUnit::Pica => "Pica",
142            BaseUnit::SurveyMile => "survey_mi",
143            BaseUnit::Yard => "yd",
144            BaseUnit::BTU => "BTU",
145            BaseUnit::ThermCalorie => "c",
146            BaseUnit::ITCalorie => "cal",
147            BaseUnit::Erg => "e",
148            BaseUnit::ElectronVolt => "eV",
149            BaseUnit::Flb => "flb",
150            BaseUnit::HPh => "HPh",
151            BaseUnit::Joule => "J",
152            BaseUnit::WattHour => "Wh",
153            BaseUnit::Dyne => "dyn",
154            BaseUnit::Newton => "N",
155            BaseUnit::Lbf => "lbf",
156            BaseUnit::Pond => "pond",
157            BaseUnit::Bit => "bit",
158            BaseUnit::Byte => "byte",
159            BaseUnit::Gauss => "ga",
160            BaseUnit::Tesla => "T",
161            BaseUnit::Gram => "g",
162            BaseUnit::Grain => "grain",
163            BaseUnit::Cwt => "cwt",
164            BaseUnit::UKCwt => "uk_cwt",
165            BaseUnit::Lbm => "lbm",
166            BaseUnit::Stone => "stone",
167            BaseUnit::Ton => "ton",
168            BaseUnit::Ozm => "ozm",
169            BaseUnit::Sg => "sg",
170            BaseUnit::AtomicMassUnit => "u",
171            BaseUnit::UKTon => "uk_ton",
172            BaseUnit::HP => "HP",
173            BaseUnit::PS => "PS",
174            BaseUnit::Watt => "W",
175            BaseUnit::Atm => "atm",
176            BaseUnit::MmHg => "mmHg",
177            BaseUnit::Pascal => "Pa",
178            BaseUnit::Psi => "psi",
179            BaseUnit::Torr => "Torr",
180            BaseUnit::AdmiralityKnot => "admkn",
181            BaseUnit::Knot => "kn",
182            BaseUnit::MetersPerHour => "m/h",
183            BaseUnit::MetersPerSecond => "m/s",
184            BaseUnit::MilesPerHour => "mph",
185            BaseUnit::Celsius => "C",
186            BaseUnit::Fahrenheit => "F",
187            BaseUnit::Kelvin => "K",
188            BaseUnit::Rankine => "Rank",
189            BaseUnit::Reaumur => "Reau",
190            BaseUnit::Day => "day",
191            BaseUnit::Hour => "hr",
192            BaseUnit::Minute => "min",
193            BaseUnit::Second => "sec",
194            BaseUnit::Year => "yr",
195            BaseUnit::CbAngstrom => "ang3",
196            BaseUnit::Barrel => "barrel",
197            BaseUnit::Bushel => "bushel",
198            BaseUnit::Cup => "cup",
199            BaseUnit::CbFoot => "ft3",
200            BaseUnit::Gallon => "gal",
201            BaseUnit::GRT => "GRT",
202            BaseUnit::CbInch => "in3",
203            BaseUnit::Liter => "l",
204            BaseUnit::CbLightYear => "ly3",
205            BaseUnit::CbMeter => "m3",
206            BaseUnit::CbMile => "mi3",
207            BaseUnit::MTon => "MTON",
208            BaseUnit::CbNauticalMile => "Mmi3",
209            BaseUnit::FluidOunce => "oz",
210            BaseUnit::CbPica => "Pica3",
211            BaseUnit::Pint => "pt",
212            BaseUnit::Quart => "qt",
213            BaseUnit::Tablespoon => "tbs",
214            BaseUnit::Teaspoon => "tsp",
215            BaseUnit::ModernTeaspoon => "tspm",
216            BaseUnit::UKGallon => "uk_gal",
217            BaseUnit::UKPint => "gu_pt",
218            BaseUnit::UKQuart => "uk_qt",
219            BaseUnit::CbYard => "yd3",
220        });
221    }
222}
223
224/// Parameter for CONVERT().
225#[derive(Debug)]
226pub enum DecimalPrefix {
227    Yotta,
228    Zetta,
229    Exa,
230    Peta,
231    Tera,
232    Giga,
233    Mega,
234    Kilo,
235    Hecto,
236    Deka,
237    Deci,
238    Centi,
239    Milli,
240    Micro,
241    Nano,
242    Pico,
243    Femto,
244    Atto,
245    Zepto,
246}
247
248impl Any for DecimalPrefix {
249    fn formula(&self, buf: &mut String) {
250        buf.push_str(match self {
251            DecimalPrefix::Yotta => "Y",
252            DecimalPrefix::Zetta => "Z",
253            DecimalPrefix::Exa => "E",
254            DecimalPrefix::Peta => "P",
255            DecimalPrefix::Tera => "T",
256            DecimalPrefix::Giga => "G",
257            DecimalPrefix::Mega => "M",
258            DecimalPrefix::Kilo => "k",
259            DecimalPrefix::Hecto => "h",
260            DecimalPrefix::Deka => "da",
261            DecimalPrefix::Deci => "d",
262            DecimalPrefix::Centi => "c",
263            DecimalPrefix::Milli => "m",
264            DecimalPrefix::Micro => "u",
265            DecimalPrefix::Nano => "n",
266            DecimalPrefix::Pico => "p",
267            DecimalPrefix::Femto => "f",
268            DecimalPrefix::Atto => "a",
269            DecimalPrefix::Zepto => "z",
270        });
271    }
272}
273
274/// Parameter for CONVERT().
275#[derive(Debug)]
276pub enum BinaryPrefix {
277    Yobi,
278    Zebi,
279    Exbi,
280    Pebi,
281    Tebi,
282    Gibi,
283    Mebi,
284    Kibi,
285}
286
287impl Any for BinaryPrefix {
288    fn formula(&self, buf: &mut String) {
289        buf.push_str(match self {
290            BinaryPrefix::Yobi => "Yi",
291            BinaryPrefix::Zebi => "Zi",
292            BinaryPrefix::Exbi => "Ei",
293            BinaryPrefix::Pebi => "Pi",
294            BinaryPrefix::Tebi => "Ti",
295            BinaryPrefix::Gibi => "Gi",
296            BinaryPrefix::Mebi => "Mi",
297            BinaryPrefix::Kibi => "Ki",
298        });
299    }
300}
301
302/// Parameter for CONVERT().
303#[derive(Debug)]
304pub enum ConvertUnit {
305    Unit(BaseUnit),
306    SI(DecimalPrefix, BaseUnit),
307    Bin(BinaryPrefix, BaseUnit),
308}
309
310impl Any for ConvertUnit {
311    #[inline]
312    fn formula(&self, buf: &mut String) {
313        match self {
314            ConvertUnit::Unit(v) => {
315                v.formula(buf);
316            }
317            ConvertUnit::SI(p, v) => {
318                p.formula(buf);
319                v.formula(buf);
320            }
321            ConvertUnit::Bin(p, v) => {
322                p.formula(buf);
323                v.formula(buf);
324            }
325        }
326    }
327}
328
329/// Parameter for SUBTOTAL().
330#[derive(Debug)]
331pub enum SubtotalFunction {
332    Average,
333    Count,
334    CountA,
335    Max,
336    Min,
337    Product,
338    StDev,
339    StDevP,
340    Sum,
341    Var,
342    VarP,
343    AverageExclCollapsed,
344    CountExclCollapsed,
345    CountAExclCollapsed,
346    MaxExclCollapsed,
347    MinExclCollapsed,
348    ProductExclCollapsed,
349    StDevExclCollapsed,
350    StDevPExclCollapsed,
351    SumExclCollapsed,
352    VarExclCollapsed,
353    VarPExclCollapsed,
354}
355
356impl Any for SubtotalFunction {
357    fn formula(&self, buf: &mut String) {
358        let _ = write!(
359            buf,
360            "{}",
361            match self {
362                SubtotalFunction::Average => 1,
363                SubtotalFunction::Count => 2,
364                SubtotalFunction::CountA => 3,
365                SubtotalFunction::Max => 4,
366                SubtotalFunction::Min => 5,
367                SubtotalFunction::Product => 6,
368                SubtotalFunction::StDev => 7,
369                SubtotalFunction::StDevP => 8,
370                SubtotalFunction::Sum => 9,
371                SubtotalFunction::Var => 10,
372                SubtotalFunction::VarP => 11,
373                SubtotalFunction::AverageExclCollapsed => 101,
374                SubtotalFunction::CountExclCollapsed => 102,
375                SubtotalFunction::CountAExclCollapsed => 103,
376                SubtotalFunction::MaxExclCollapsed => 104,
377                SubtotalFunction::MinExclCollapsed => 105,
378                SubtotalFunction::ProductExclCollapsed => 106,
379                SubtotalFunction::StDevExclCollapsed => 107,
380                SubtotalFunction::StDevPExclCollapsed => 108,
381                SubtotalFunction::SumExclCollapsed => 109,
382                SubtotalFunction::VarExclCollapsed => 110,
383                SubtotalFunction::VarPExclCollapsed => 111,
384            }
385        );
386    }
387}
388
389/// Parameter for AGGREGATE().
390#[derive(Debug)]
391pub enum AggregateFunction {
392    Average,
393    Count,
394    CountA,
395    Max,
396    Min,
397    Product,
398    StDevS,
399    StDevP,
400    Sum,
401    VarS,
402    VarP,
403    Median,
404    ModeSngl,
405    Large,
406    Small,
407    PercentileInc,
408    QuartileInc,
409    PercentileExc,
410    QuartileExc,
411}
412
413impl Any for AggregateFunction {
414    fn formula(&self, buf: &mut String) {
415        let _ = write!(
416            buf,
417            "{}",
418            match self {
419                AggregateFunction::Average => 1,
420                AggregateFunction::Count => 2,
421                AggregateFunction::CountA => 3,
422                AggregateFunction::Max => 4,
423                AggregateFunction::Min => 5,
424                AggregateFunction::Product => 6,
425                AggregateFunction::StDevS => 7,
426                AggregateFunction::StDevP => 8,
427                AggregateFunction::Sum => 9,
428                AggregateFunction::VarS => 10,
429                AggregateFunction::VarP => 11,
430                AggregateFunction::Median => 12,
431                AggregateFunction::ModeSngl => 13,
432                AggregateFunction::Large => 14,
433                AggregateFunction::Small => 15,
434                AggregateFunction::PercentileInc => 16,
435                AggregateFunction::QuartileInc => 17,
436                AggregateFunction::PercentileExc => 18,
437                AggregateFunction::QuartileExc => 19,
438            }
439        );
440    }
441}
442
443/// Parameter for AGGREGATE().
444#[derive(Debug)]
445pub enum AggregateOption {
446    /// Ignore only nested SUBTOTAL and AGGREGATE functions
447    IgnoreNSA,
448    /// Ignore only hidden rows, nested SUBTOTAL and AGGREGATE functions
449    IgnoreHNSA,
450    /// Ignore only errors, nested SUBTOTAL and AGGREGATE functions
451    IgnoreENSA,
452    /// Ignore hidden rows, errors, nested SUBTOTAL and AGGREGATE functions
453    IgnoreHENSA,
454    /// Ignore nothing
455    IgnoreNone,
456    /// Ignore only hidden rows
457    IgnoreH,
458    /// Ignore only errors
459    IgnoreE,
460    /// Ignore only hidden rows and errors
461    IgnoreHE,
462}
463
464impl Any for AggregateOption {
465    fn formula(&self, buf: &mut String) {
466        let _ = write!(
467            buf,
468            "{}",
469            match self {
470                AggregateOption::IgnoreNSA => 0,
471                AggregateOption::IgnoreHNSA => 1,
472                AggregateOption::IgnoreENSA => 2,
473                AggregateOption::IgnoreHENSA => 3,
474                AggregateOption::IgnoreNone => 4,
475                AggregateOption::IgnoreH => 5,
476                AggregateOption::IgnoreE => 6,
477                AggregateOption::IgnoreHE => 7,
478            }
479        );
480    }
481}
482
483#[inline]
484pub fn sumifs<
485    A: Reference + 'static,
486    R: Reference + 'static,
487    C: Criterion + 'static,
488    const N: usize,
489>(
490    range: A,
491    list: [(R, C); N],
492) -> FnNumberVar {
493    let mut param: Vec<Box<dyn Any>> = Vec::new();
494
495    param.push(Box::new(range));
496    for (r, c) in list {
497        param.push(Box::new(r));
498        param.push(Box::new(c));
499    }
500
501    FnNumberVar("SUMIFS", param)
502}