Multiplication and division support for electric units
This commit is contained in:
parent
3a0518e82d
commit
850e2cede5
117
src/units.rs
117
src/units.rs
@ -203,6 +203,7 @@ create_units!(
|
|||||||
TerawattHour: (Energy, d128!(3600000000000000)),
|
TerawattHour: (Energy, d128!(3600000000000000)),
|
||||||
PetawattHour: (Energy, d128!(3600000000000000000)),
|
PetawattHour: (Energy, d128!(3600000000000000000)),
|
||||||
|
|
||||||
|
// ! If updating Milliwatt, also update get_inverted_milliwatt_weight()
|
||||||
Milliwatt: (Power, d128!(0.001)),
|
Milliwatt: (Power, d128!(0.001)),
|
||||||
Watt: (Power, d128!(1)),
|
Watt: (Power, d128!(1)),
|
||||||
Kilowatt: (Power, d128!(1000)),
|
Kilowatt: (Power, d128!(1000)),
|
||||||
@ -215,18 +216,21 @@ create_units!(
|
|||||||
Horsepower: (Power, d128!(745.69987158227022)), // exact according to wikipedia
|
Horsepower: (Power, d128!(745.69987158227022)), // exact according to wikipedia
|
||||||
MetricHorsepower: (Power, d128!(735.49875)),
|
MetricHorsepower: (Power, d128!(735.49875)),
|
||||||
|
|
||||||
Milliampere: (ElectricCurrent, d128!(1)),
|
// ! If updating Milliampere, also update get_inverted_milliampere_weight()
|
||||||
Ampere: (ElectricCurrent, d128!(1000)),
|
Milliampere: (ElectricCurrent, d128!(0.001)),
|
||||||
Kiloampere: (ElectricCurrent, d128!(1000000)),
|
Ampere: (ElectricCurrent, d128!(1)),
|
||||||
Abampere: (ElectricCurrent, d128!(10000)),
|
Kiloampere: (ElectricCurrent, d128!(1000)),
|
||||||
|
Abampere: (ElectricCurrent, d128!(10)),
|
||||||
|
|
||||||
Milliohm: (Resistance, d128!(1)),
|
// ! If updating Milliohm, also update get_inverted_milliohm_weight()
|
||||||
Ohm: (Resistance, d128!(1000)),
|
Milliohm: (Resistance, d128!(0.001)),
|
||||||
Kiloohm: (Resistance, d128!(1000000)),
|
Ohm: (Resistance, d128!(1)),
|
||||||
|
Kiloohm: (Resistance, d128!(1000)),
|
||||||
|
|
||||||
Millivolt: (Voltage, d128!(1)),
|
// ! If updating Millivolt, also update get_inverted_millivolt_weight()
|
||||||
Volt: (Voltage, d128!(1000)),
|
Millivolt: (Voltage, d128!(0.001)),
|
||||||
Kilovolt: (Voltage, d128!(1000000)),
|
Volt: (Voltage, d128!(1)),
|
||||||
|
Kilovolt: (Voltage, d128!(1000)),
|
||||||
|
|
||||||
Pascal: (Pressure, d128!(1)),
|
Pascal: (Pressure, d128!(1)),
|
||||||
Kilopascal: (Pressure, d128!(1000)),
|
Kilopascal: (Pressure, d128!(1000)),
|
||||||
@ -256,6 +260,21 @@ create_units!(
|
|||||||
Fahrenheit: (Temperature, d128!(0)),
|
Fahrenheit: (Temperature, d128!(0)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// These functions are here to avoid dividing by small numbers like 0.01,
|
||||||
|
// because d128 gives numbers in E notation in that case.
|
||||||
|
fn get_inverted_milliwatt_weight() -> d128 {
|
||||||
|
return d128!(1000);
|
||||||
|
}
|
||||||
|
fn get_inverted_milliohm_weight() -> d128 {
|
||||||
|
return d128!(1000);
|
||||||
|
}
|
||||||
|
fn get_inverted_milliampere_weight() -> d128 {
|
||||||
|
return d128!(1000);
|
||||||
|
}
|
||||||
|
fn get_inverted_millivolt_weight() -> d128 {
|
||||||
|
return d128!(1000);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the conversion factor between two units.
|
/// Returns the conversion factor between two units.
|
||||||
///
|
///
|
||||||
/// The conversion factor is what you need to multiply `unit` with to get
|
/// The conversion factor is what you need to multiply `unit` with to get
|
||||||
@ -377,6 +396,46 @@ pub fn to_ideal_unit(number: Number) -> Number {
|
|||||||
} else {
|
} else {
|
||||||
return Number::new(value, CubicMillimeter)
|
return Number::new(value, CubicMillimeter)
|
||||||
}
|
}
|
||||||
|
} else if number.unit.category() == Power {
|
||||||
|
if value >= d128!(1000000000000000) { // 1 petawatt
|
||||||
|
return Number::new(value/Petawatt.weight(), Petawatt)
|
||||||
|
} else if value >= d128!(1000000000000) { // 1 terawatt
|
||||||
|
return Number::new(value/Terawatt.weight(), Terawatt)
|
||||||
|
} else if value >= d128!(1000000000) { // 1 gigawatt
|
||||||
|
return Number::new(value/Gigawatt.weight(), Gigawatt)
|
||||||
|
} else if value >= d128!(1000000) { // megawatt
|
||||||
|
return Number::new(value/Megawatt.weight(), Megawatt)
|
||||||
|
} else if value >= d128!(1000) { // 1 kilowatt
|
||||||
|
return Number::new(value/Kilowatt.weight(), Kilowatt)
|
||||||
|
} else if value >= d128!(1) { // 1 watt
|
||||||
|
return Number::new(value, Watt)
|
||||||
|
} else {
|
||||||
|
return Number::new(value * get_inverted_milliwatt_weight(), Milliwatt)
|
||||||
|
}
|
||||||
|
} else if number.unit.category() == ElectricCurrent {
|
||||||
|
if value >= d128!(1000) { // 1 kiloampere
|
||||||
|
return Number::new(value/Kiloampere.weight(), Kiloampere)
|
||||||
|
} else if value >= d128!(1) { // 1 ampere
|
||||||
|
return Number::new(value, Ampere)
|
||||||
|
} else {
|
||||||
|
return Number::new(value * get_inverted_milliampere_weight(), Milliampere)
|
||||||
|
}
|
||||||
|
} else if number.unit.category() == Resistance {
|
||||||
|
if value >= d128!(1000) { // 1 kiloohm
|
||||||
|
return Number::new(value/Kiloohm.weight(), Kiloohm)
|
||||||
|
} else if value >= d128!(1) { // 1 ohm
|
||||||
|
return Number::new(value, Ohm)
|
||||||
|
} else {
|
||||||
|
return Number::new(value * get_inverted_milliohm_weight(), Milliohm)
|
||||||
|
}
|
||||||
|
} else if number.unit.category() == Voltage {
|
||||||
|
if value >= d128!(1000) { // 1 kilovolt
|
||||||
|
return Number::new(value/Kilovolt.weight(), Kilovolt)
|
||||||
|
} else if value >= d128!(1) { // 1 volt
|
||||||
|
return Number::new(value, Volt)
|
||||||
|
} else {
|
||||||
|
return Number::new(value * get_inverted_millivolt_weight(), Millivolt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
number
|
number
|
||||||
}
|
}
|
||||||
@ -387,6 +446,8 @@ pub fn to_ideal_unit(number: Number) -> Number {
|
|||||||
/// - If you multiply `NoType` with any other unit, the result gets that other unit
|
/// - If you multiply `NoType` with any other unit, the result gets that other unit
|
||||||
/// - If you multiply `Length` with `Length`, the result has a unit of `Area`, etc.
|
/// - If you multiply `Length` with `Length`, the result has a unit of `Area`, etc.
|
||||||
/// - If you multiply `Speed` with `Time`, the result has a unit of `Length`
|
/// - If you multiply `Speed` with `Time`, the result has a unit of `Length`
|
||||||
|
/// - If you multiply `Voltage` with `Current`, the result has a unit of `Power`
|
||||||
|
/// - If you multiply `Current` with `Resistance`, the result has a unit of `Voltage`
|
||||||
pub fn multiply(left: Number, right: Number) -> Result<Number, String> {
|
pub fn multiply(left: Number, right: Number) -> Result<Number, String> {
|
||||||
Ok(actual_multiply(left, right, false)?)
|
Ok(actual_multiply(left, right, false)?)
|
||||||
}
|
}
|
||||||
@ -401,7 +462,7 @@ fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result<Number,
|
|||||||
// if temperature
|
// if temperature
|
||||||
Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||||
} else if left.unit == NoUnit && right.unit != NoUnit {
|
} else if left.unit == NoUnit && right.unit != NoUnit {
|
||||||
// 3 * 1 anyunit
|
// 3 * 2 anyunit
|
||||||
Ok(Number::new(left.value * right.value, right.unit))
|
Ok(Number::new(left.value * right.value, right.unit))
|
||||||
} else if lcat == Length && rcat == Length {
|
} else if lcat == Length && rcat == Length {
|
||||||
// length * length
|
// length * length
|
||||||
@ -426,9 +487,17 @@ fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result<Number,
|
|||||||
};
|
};
|
||||||
let kilometers = Number::new(result, Kilometer);
|
let kilometers = Number::new(result, Kilometer);
|
||||||
Ok(convert(kilometers, final_unit)?)
|
Ok(convert(kilometers, final_unit)?)
|
||||||
|
} else if lcat == Voltage && rcat == ElectricCurrent {
|
||||||
|
// 1 volt * 1 ampere = 1 watt
|
||||||
|
let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight());
|
||||||
|
Ok(to_ideal_unit(Number::new(result, Watt)))
|
||||||
|
} else if lcat == ElectricCurrent && rcat == Resistance {
|
||||||
|
// 1 amp * 1 ohm = 1 volt
|
||||||
|
let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight());
|
||||||
|
Ok(to_ideal_unit(Number::new(result, Watt)))
|
||||||
} else {
|
} else {
|
||||||
if swapped == true {
|
if swapped == true {
|
||||||
Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
Err(format!("Cannot multiply {:?} and {:?}", right.unit, left.unit))
|
||||||
} else {
|
} else {
|
||||||
actual_multiply(right, left, true)
|
actual_multiply(right, left, true)
|
||||||
}
|
}
|
||||||
@ -439,8 +508,12 @@ fn actual_multiply(left: Number, right: Number, swapped: bool) -> Result<Number,
|
|||||||
///
|
///
|
||||||
/// - Temperatures don't work
|
/// - Temperatures don't work
|
||||||
/// - If you divide a unit by that same unit, the result has a unit of `NoType`
|
/// - If you divide a unit by that same unit, the result has a unit of `NoType`
|
||||||
/// - If you divide `Volume` by `Length`, the result has a a unit of `Area`, etc.
|
/// - If you divide `Volume` by `Length`, the result has a unit of `Area`, etc.
|
||||||
/// - If you divide `Length` by `Time`, the result has a a unit of `Speed`
|
/// - If you divide `Length` by `Time`, the result has a unit of `Speed`
|
||||||
|
/// - If you divide `Power` by `ElectricCurrent`, the result has a unit of `Volt`
|
||||||
|
/// - If you divide `Voltage` by `ElectricCurrent`, the result has a unit of `Ohm`
|
||||||
|
/// - If you divide `Voltage` by `Resistance`, the result has a unit of `Ampere`
|
||||||
|
/// - If you divide `Power` by `Voltage`, the result has a unit of `Ampere`
|
||||||
pub fn divide(left: Number, right: Number) -> Result<Number, String> {
|
pub fn divide(left: Number, right: Number) -> Result<Number, String> {
|
||||||
let lcat = left.unit.category();
|
let lcat = left.unit.category();
|
||||||
let rcat = right.unit.category();
|
let rcat = right.unit.category();
|
||||||
@ -479,6 +552,22 @@ pub fn divide(left: Number, right: Number) -> Result<Number, String> {
|
|||||||
let hours = convert(right, Hour)?;
|
let hours = convert(right, Hour)?;
|
||||||
let kph = Number::new(kilometers.value / hours.value, KilometersPerHour);
|
let kph = Number::new(kilometers.value / hours.value, KilometersPerHour);
|
||||||
Ok(convert(kph, final_unit)?)
|
Ok(convert(kph, final_unit)?)
|
||||||
|
} else if lcat == Power && rcat == ElectricCurrent {
|
||||||
|
// 1 watt / 1 ampere = 1 volt
|
||||||
|
let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight());
|
||||||
|
Ok(to_ideal_unit(Number::new(result, Volt)))
|
||||||
|
} else if lcat == Voltage && rcat == ElectricCurrent {
|
||||||
|
// 1 volt / 1 ampere = 1 ohm
|
||||||
|
let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight());
|
||||||
|
Ok(to_ideal_unit(Number::new(result, Ohm)))
|
||||||
|
} else if lcat == Voltage && rcat == Resistance {
|
||||||
|
// 1 volt / 1 ohm = 1 amp
|
||||||
|
let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight());
|
||||||
|
Ok(to_ideal_unit(Number::new(result, Ampere)))
|
||||||
|
} else if lcat == Power && rcat == Voltage {
|
||||||
|
// 1 watt / 1 volt = 1 amp
|
||||||
|
let result = (left.value * left.unit.weight()) / (right.value * right.unit.weight());
|
||||||
|
Ok(to_ideal_unit(Number::new(result, Ampere)))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user