Skip to content

Commit 083ec0f

Browse files
committed
v0.6.0
1 parent 7f44e3d commit 083ec0f

22 files changed

Lines changed: 179 additions & 155 deletions

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
### 0.6.0
2+
* Renamed `systems` to `units`
3+
* Moved scalar units to `units/scalar.dart`
4+
* Quantity.scaled() now accepts a `num` as well as a `Quantity`
5+
16
### 0.5.1
27
* Fixed prefixed unit scaling [2c393b1](https://github.com/nebkat/dart-physical/commit/2c393b1a9836ca5ea5aae435c866167feceda6b4)
38
* Reorganized examples

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ dart pub add physical
2828

2929
```dart
3030
import 'package:physical/physical.dart';
31-
import 'package:physical/system/si.dart' as si;
31+
import 'package:physical/units/si.dart' as si;
3232
3333
// ----- UNCHECKED -----
3434
@@ -139,7 +139,7 @@ In addition to this, units hold information about their symbol and name for disp
139139

140140
Many common units are already provided by the library:
141141
```dart
142-
// Provided in 'package:physical/system/si.dart'
142+
// Provided in 'package:physical/units/si.dart'
143143
// Or in 'package:physical/units.dart'
144144
const second = SiNamedUnit(
145145
symbol: 's',

example/physical.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'package:physical/core.dart';
22
import 'package:physical/quantities.dart';
3-
import 'package:physical/system/si.dart' as si;
4-
import 'package:physical/system/international.dart' as intl;
5-
import 'package:physical/system/usc.dart' as usc;
3+
import 'package:physical/units/international.dart' as intl;
4+
import 'package:physical/units/si.dart' as si;
5+
import 'package:physical/units/usc.dart' as usc;
66

77
void main() {
88
construction();

lib/core.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ library;
55
export 'src/core/dimensions.dart';
66
export 'src/core/exception.dart';
77
export 'src/core/quantity.dart';
8+
export 'src/core/scalar.dart';
89
export 'src/core/unit.dart';

lib/src/common/quantities.dart

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,181 +1,182 @@
11
import '../core/quantity.dart';
22
import '../core/unit.dart';
3-
import '../system/si.dart';
4-
import '../system/usc.dart';
3+
import '../units/si.dart' as si;
4+
import '../units/usc.dart' as usc show degreeFahrenheit, zerothDegreeFahrenheit;
55
import 'dimensions.dart';
66

77
extension type Angle._(Quantity q) implements DimensionedQuantity<Angle> {
88
Angle(Quantity q) : q = angle.checked(q);
9-
const Angle.zero() : q = const Quantity.of(0, radian);
9+
const Angle.zero() : q = const Quantity.of(0, si.radian);
1010
Angle.of(num value, Unit unit) : this(Quantity.of(value, unit));
11-
Angle.degrees(num value) : this._(Quantity.of(value, degree));
12-
Angle.radians(num value) : this._(Quantity.of(value, radian));
11+
Angle.degrees(num value) : this._(Quantity.of(value, si.degree));
12+
Angle.radians(num value) : this._(Quantity.of(value, si.radian));
1313
}
1414

1515
extension type Length._(Quantity q) implements DimensionedQuantity<Length> {
1616
Length(Quantity q) : q = length.checked(q);
17-
const Length.zero() : q = const Quantity.of(0, metre);
17+
const Length.zero() : q = const Quantity.of(0, si.metre);
1818
Length.of(num value, Unit unit) : this._(Quantity.of(value, unit));
19-
Length.metres(num value) : this._(Quantity.of(value, metre));
19+
Length.metres(num value) : this._(Quantity.of(value, si.metre));
2020
}
2121

2222
extension type Mass._(Quantity q) implements DimensionedQuantity<Mass> {
2323
Mass(Quantity q) : q = mass.checked(q);
24-
const Mass.zero() : q = const Quantity.of(0, kilogram);
24+
const Mass.zero() : q = const Quantity.of(0, si.kilogram);
2525
Mass.of(num value, Unit unit) : this._(Quantity.of(value, unit));
26-
Mass.grams(num value) : this._(Quantity.of(value, gram));
27-
Mass.kilograms(num value) : this._(Quantity.of(value, kilogram));
26+
Mass.grams(num value) : this._(Quantity.of(value, si.gram));
27+
Mass.kilograms(num value) : this._(Quantity.of(value, si.kilogram));
2828
}
2929

3030
extension type Area._(Quantity q) implements DimensionedQuantity<Area> {
3131
Area(Quantity q) : q = area.checked(q);
32-
const Area.zero() : q = const Quantity.of(0, squareMetre);
32+
const Area.zero() : q = const Quantity.of(0, si.squareMetre);
3333
Area.of(num value, Unit unit) : this(Quantity.of(value, unit));
34-
Area.squareMetres(num value) : this._(Quantity.of(value, squareMetre));
35-
Area.hectares(num value) : this._(Quantity.of(value, hectare));
34+
Area.squareMetres(num value) : this._(Quantity.of(value, si.squareMetre));
35+
Area.hectares(num value) : this._(Quantity.of(value, si.hectare));
3636
}
3737

3838
extension type Volume._(Quantity q) implements DimensionedQuantity<Volume> {
3939
Volume(Quantity q) : q = volume.checked(q);
40-
const Volume.zero() : q = const Quantity.of(0, cubicMetre);
40+
const Volume.zero() : q = const Quantity.of(0, si.cubicMetre);
4141
Volume.of(num value, Unit unit) : this(Quantity.of(value, unit));
42-
Volume.litres(num value) : this._(Quantity.of(value, litre));
43-
Volume.cubicMetres(num value) : this._(Quantity.of(value, cubicMetre));
42+
Volume.litres(num value) : this._(Quantity.of(value, si.litre));
43+
Volume.cubicMetres(num value) : this._(Quantity.of(value, si.cubicMetre));
4444
}
4545

4646
extension type MassPerVolume._(Quantity q) implements DimensionedQuantity<MassPerVolume> {
4747
MassPerVolume(Quantity q) : q = massPerVolume.checked(q);
48-
const MassPerVolume.zero() : q = const Quantity.of(0, kilogramPerCubicMetre);
48+
const MassPerVolume.zero() : q = const Quantity.of(0, si.kilogramPerCubicMetre);
4949
MassPerVolume.of(num value, Unit unit) : this(Quantity.of(value, unit));
50-
MassPerVolume.kilogramsPerCubicMetre(num value) : this._(Quantity.of(value, kilogram / cubicMetre));
51-
MassPerVolume.gramsPerCubicCentimetre(num value) : this._(Quantity.of(value, gram / (metre.centi ^ 3)));
50+
MassPerVolume.kilogramsPerCubicMetre(num value) : this._(Quantity.of(value, si.kilogram / si.cubicMetre));
51+
MassPerVolume.gramsPerCubicCentimetre(num value) : this._(Quantity.of(value, si.gram / (si.metre.centi ^ 3)));
5252
}
5353

5454
extension type VolumePerMass._(Quantity q) implements DimensionedQuantity<VolumePerMass> {
5555
VolumePerMass(Quantity q) : q = volumePerMass.checked(q);
56-
const VolumePerMass.zero() : q = const Quantity.of(0, cubicMetrePerKilogram);
56+
const VolumePerMass.zero() : q = const Quantity.of(0, si.cubicMetrePerKilogram);
5757
VolumePerMass.of(num value, Unit unit) : this(Quantity.of(value, unit));
58-
VolumePerMass.cubicMetresPerKilogram(num value) : this._(Quantity.of(value, cubicMetre / kilogram));
58+
VolumePerMass.cubicMetresPerKilogram(num value) : this._(Quantity.of(value, si.cubicMetre / si.kilogram));
5959
}
6060

6161
extension type Time._(Quantity q) implements DimensionedQuantity<Time> {
6262
Time(Quantity q) : q = time.checked(q);
63-
const Time.zero() : q = const Quantity.of(0, second);
63+
const Time.zero() : q = const Quantity.of(0, si.second);
6464
Time.of(num value, Unit unit) : this(Quantity.of(value, unit));
65-
Time.microseconds(num value) : this._(Quantity.of(value, second.micro));
66-
Time.milliseconds(num value) : this._(Quantity.of(value, second.milli));
67-
Time.seconds(num value) : this._(Quantity.of(value, second));
68-
Time.minutes(num value) : this._(Quantity.of(value, minute));
69-
Time.hours(num value) : this._(Quantity.of(value, hour));
65+
Time.microseconds(num value) : this._(Quantity.of(value, si.second.micro));
66+
Time.milliseconds(num value) : this._(Quantity.of(value, si.second.milli));
67+
Time.seconds(num value) : this._(Quantity.of(value, si.second));
68+
Time.minutes(num value) : this._(Quantity.of(value, si.minute));
69+
Time.hours(num value) : this._(Quantity.of(value, si.hour));
7070
Time.hms(int hours, int minutes, int seconds)
7171
: this(Time.hours(hours) + Time.minutes(minutes) + Time.seconds(seconds));
7272
Time.duration(Duration duration) : this.microseconds(duration.inMicroseconds);
7373
}
7474

7575
extension type Temperature._(QuantityPoint qp) implements QuantityPoint {
7676
Temperature(this.qp) : assert(qp.quantity.dimensions == temperature, "${qp.quantity.dimensions} != $temperature");
77-
const Temperature.absoluteZero() : qp = const QuantityPoint(Quantity.of(0, kelvin), absoluteZeroKelvin);
78-
const Temperature.icePoint() : qp = const QuantityPoint(Quantity.of(0, degreeCelsius), zerothDegreeCelsius);
77+
const Temperature.absoluteZero() : qp = const QuantityPoint(Quantity.of(0, si.kelvin), si.absoluteZeroKelvin);
78+
const Temperature.icePoint() : qp = const QuantityPoint(Quantity.of(0, si.degreeCelsius), si.zerothDegreeCelsius);
7979
Temperature.of(num value, Unit unit, QuantityOrigin origin) : this(origin + Quantity.of(value, unit));
80-
Temperature.kelvins(num value) : this._(absoluteZeroKelvin + Quantity.of(value, kelvin));
81-
Temperature.degreesCelsius(num value) : this._(zerothDegreeCelsius + Quantity.of(value, degreeCelsius));
82-
Temperature.degreesFahrenheit(num value) : this._(zerothDegreeFahrenheit + Quantity.of(value, degreeFahrenheit));
80+
Temperature.kelvins(num value) : this._(si.absoluteZeroKelvin + Quantity.of(value, si.kelvin));
81+
Temperature.degreesCelsius(num value) : this._(si.zerothDegreeCelsius + Quantity.of(value, si.degreeCelsius));
82+
Temperature.degreesFahrenheit(num value)
83+
: this._(usc.zerothDegreeFahrenheit + Quantity.of(value, usc.degreeFahrenheit));
8384

8485
Temperature inDegreesCelsius() => Temperature(
85-
qp.withOrigin(zerothDegreeCelsius).inUnits(degreeCelsius),
86+
qp.withOrigin(si.zerothDegreeCelsius).inUnits(si.degreeCelsius),
8687
);
8788
Temperature inDegreesFahrenheit() => Temperature(
88-
qp.withOrigin(zerothDegreeFahrenheit).inUnits(degreeFahrenheit),
89+
qp.withOrigin(usc.zerothDegreeFahrenheit).inUnits(usc.degreeFahrenheit),
8990
);
9091
}
9192

9293
extension type Speed._(Quantity q) implements DimensionedQuantity<Speed> {
9394
Speed(Quantity q) : q = speed.checked(q);
94-
const Speed.zero() : q = const Quantity.of(0, metrePerSecond);
95+
const Speed.zero() : q = const Quantity.of(0, si.metrePerSecond);
9596
Speed.of(num value, Unit unit) : this(Quantity.of(value, unit));
96-
Speed.metresPerSecond(num value) : this._(Quantity.of(value, metrePerSecond));
97+
Speed.metresPerSecond(num value) : this._(Quantity.of(value, si.metrePerSecond));
9798
}
9899

99100
extension type Acceleration._(Quantity q) implements DimensionedQuantity<Acceleration> {
100101
Acceleration(Quantity q) : q = acceleration.checked(q);
101-
const Acceleration.zero() : q = const Quantity.of(0, metrePerSecondSquared);
102+
const Acceleration.zero() : q = const Quantity.of(0, si.metrePerSecondSquared);
102103
Acceleration.of(num value, Unit unit) : this(Quantity.of(value, unit));
103-
Acceleration.metresPerSecondSquared(num value) : this._(Quantity.of(value, metrePerSecondSquared));
104+
Acceleration.metresPerSecondSquared(num value) : this._(Quantity.of(value, si.metrePerSecondSquared));
104105
}
105106

106107
extension type Capacitance._(Quantity q) implements DimensionedQuantity<Capacitance> {
107108
Capacitance(Quantity q) : q = capacitance.checked(q);
108-
const Capacitance.zero() : q = const Quantity.of(0, farad);
109+
const Capacitance.zero() : q = const Quantity.of(0, si.farad);
109110
Capacitance.of(num value, Unit unit) : this(Quantity.of(value, unit));
110-
Capacitance.farads(num value) : this._(Quantity.of(value, farad));
111+
Capacitance.farads(num value) : this._(Quantity.of(value, si.farad));
111112
}
112113

113114
extension type Frequency._(Quantity q) implements DimensionedQuantity<Frequency> {
114115
Frequency(Quantity q) : q = frequency.checked(q);
115-
const Frequency.zero() : q = const Quantity.of(0, hertz);
116+
const Frequency.zero() : q = const Quantity.of(0, si.hertz);
116117
Frequency.of(num value, Unit unit) : this(Quantity.of(value, unit));
117-
Frequency.hertz(num value) : this._(Quantity.of(value, hertz));
118+
Frequency.hertz(num value) : this._(Quantity.of(value, si.hertz));
118119
}
119120

120121
extension type Voltage._(Quantity q) implements DimensionedQuantity<Voltage> {
121122
Voltage(Quantity q) : q = voltage.checked(q);
122-
const Voltage.zero() : q = const Quantity.of(0, volt);
123+
const Voltage.zero() : q = const Quantity.of(0, si.volt);
123124
Voltage.of(num value, Unit unit) : this(Quantity.of(value, unit));
124125
}
125126

126127
extension type Current._(Quantity q) implements DimensionedQuantity<Current> {
127128
Current(Quantity q) : q = electricCurrent.checked(q);
128-
const Current.zero() : q = const Quantity.of(0, ampere);
129+
const Current.zero() : q = const Quantity.of(0, si.ampere);
129130
Current.of(num value, Unit unit) : this(Quantity.of(value, unit));
130-
Current.amperes(num value) : this._(Quantity.of(value, ampere));
131+
Current.amperes(num value) : this._(Quantity.of(value, si.ampere));
131132
}
132133

133134
extension type Resistance._(Quantity q) implements DimensionedQuantity<Resistance> {
134135
Resistance(Quantity q) : q = resistance.checked(q);
135-
const Resistance.zero() : q = const Quantity.of(0, ohm);
136+
const Resistance.zero() : q = const Quantity.of(0, si.ohm);
136137
Resistance.of(num value, Unit unit) : this(Quantity.of(value, unit));
137-
Resistance.ohms(num value) : this._(Quantity.of(value, ohm));
138+
Resistance.ohms(num value) : this._(Quantity.of(value, si.ohm));
138139
}
139140

140141
extension type Power._(Quantity q) implements DimensionedQuantity<Power> {
141142
Power(Quantity q) : q = power.checked(q);
142-
const Power.zero() : q = const Quantity.of(0, watt);
143+
const Power.zero() : q = const Quantity.of(0, si.watt);
143144
Power.of(num value, Unit unit) : this(Quantity.of(value, unit));
144-
Power.watts(num value) : this._(Quantity.of(value, watt));
145+
Power.watts(num value) : this._(Quantity.of(value, si.watt));
145146
}
146147

147148
extension type Energy._(Quantity q) implements DimensionedQuantity<Energy> {
148149
Energy(Quantity q) : q = energy.checked(q);
149-
const Energy.zero() : q = const Quantity.of(0, joule);
150+
const Energy.zero() : q = const Quantity.of(0, si.joule);
150151
Energy.of(num value, Unit unit) : this(Quantity.of(value, unit));
151-
Energy.joules(num value) : this._(Quantity.of(value, joule));
152-
Energy.wattHours(num value) : this._(Quantity.of(value, wattHour));
152+
Energy.joules(num value) : this._(Quantity.of(value, si.joule));
153+
Energy.wattHours(num value) : this._(Quantity.of(value, si.wattHour));
153154
}
154155

155156
extension type MassPerTime._(Quantity q) implements DimensionedQuantity<MassPerTime> {
156157
MassPerTime(Quantity q) : q = massPerTime.checked(q);
157-
const MassPerTime.zero() : q = const Quantity.of(0, kilogramPerSecond);
158+
const MassPerTime.zero() : q = const Quantity.of(0, si.kilogramPerSecond);
158159
MassPerTime.of(num value, Unit unit) : this(Quantity.of(value, unit));
159-
MassPerTime.kilogramsPerSecond(num value) : this._(Quantity.of(value, kilogramPerSecond));
160+
MassPerTime.kilogramsPerSecond(num value) : this._(Quantity.of(value, si.kilogramPerSecond));
160161
}
161162

162163
extension type MassPerArea._(Quantity q) implements DimensionedQuantity<MassPerArea> {
163164
MassPerArea(Quantity q) : q = massPerArea.checked(q);
164-
const MassPerArea.zero() : q = const Quantity.of(0, kilogramPerSquareMetre);
165+
const MassPerArea.zero() : q = const Quantity.of(0, si.kilogramPerSquareMetre);
165166
MassPerArea.of(num value, Unit unit) : this(Quantity.of(value, unit));
166-
MassPerArea.kilogramsPerSquareMetre(num value) : this._(Quantity.of(value, kilogramPerSquareMetre));
167+
MassPerArea.kilogramsPerSquareMetre(num value) : this._(Quantity.of(value, si.kilogramPerSquareMetre));
167168
}
168169

169170
extension type VolumePerTime._(Quantity q) implements DimensionedQuantity<VolumePerTime> {
170171
VolumePerTime(Quantity q) : q = volumePerTime.checked(q);
171-
const VolumePerTime.zero() : q = const Quantity.of(0, cubicMetrePerSecond);
172+
const VolumePerTime.zero() : q = const Quantity.of(0, si.cubicMetrePerSecond);
172173
VolumePerTime.of(num value, Unit unit) : this(Quantity.of(value, unit));
173-
VolumePerTime.cubicMetresPerSecond(num value) : this._(Quantity.of(value, cubicMetrePerSecond));
174+
VolumePerTime.cubicMetresPerSecond(num value) : this._(Quantity.of(value, si.cubicMetrePerSecond));
174175
}
175176

176177
extension type VolumePerArea._(Quantity q) implements DimensionedQuantity<VolumePerArea> {
177178
VolumePerArea(Quantity q) : q = volumePerArea.checked(q);
178-
const VolumePerArea.zero() : q = const Quantity.of(0, cubicMetrePerSquareMetre);
179+
const VolumePerArea.zero() : q = const Quantity.of(0, si.cubicMetrePerSquareMetre);
179180
VolumePerArea.of(num value, Unit unit) : this(Quantity.of(value, unit));
180-
VolumePerArea.cubicMetresPerSquareMetre(num value) : this._(Quantity.of(value, cubicMetrePerSquareMetre));
181+
VolumePerArea.cubicMetresPerSquareMetre(num value) : this._(Quantity.of(value, si.cubicMetrePerSquareMetre));
181182
}

lib/src/core/quantity.dart

Lines changed: 8 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import 'dart:math' as math;
22

3-
import 'package:physical/src/system/si.dart';
4-
5-
import '../common/units.dart';
63
import 'dimensions.dart';
74
import 'exception.dart';
85
import 'unit.dart';
@@ -176,10 +173,12 @@ class Quantity implements Comparable<Quantity> {
176173
/// A ceiled copy of this quantity.
177174
Quantity ceil() => Quantity.of(value.ceil(), unit);
178175

179-
/// A copy of this quantity scaled by [other].
176+
/// A copy of this quantity scaled by [scalar].
177+
///
178+
/// [scalar] must be a scalar [Quantity] or a [num].
180179
///
181180
/// See also [DimensionedQuantity.scaled].
182-
Quantity scaled(Scalar other) => this * other;
181+
Quantity scaled(Object scalar) => this * Dimensions.empty().checked(numToScalar(scalar));
183182

184183
/// Whether this quantity is numerically smaller than [other] in common units.
185184
bool operator <(Quantity other) => compareTo(other) < 0;
@@ -420,64 +419,10 @@ extension type DimensionedQuantity<T>._(Quantity q) implements Quantity {
420419
T floor() => q.floor() as T;
421420
T ceil() => q.ceil() as T;
422421

423-
/// A copy of this quantity scaled by [other].
422+
/// A copy of this quantity scaled by [scalar].
424423
///
425-
/// Unlike [operator *], this operation is guaranteed to return the same type [T].
426-
T scaled(Scalar other) => q.scaled(other) as T;
427-
}
428-
429-
/// A dimensionless scalar [Quantity].
430-
///
431-
/// Specialization of [Quantity] that provides stronger typing on many operations
432-
/// that are guaranteed to return a scalar result.
433-
///
434-
/// Allows interaction with raw [num] values in addition, subtraction and comparison.
435-
extension type Scalar._(Quantity q) implements DimensionedQuantity<Scalar> {
436-
Scalar(Quantity q) : q = Dimensions.empty().checked(q);
437-
const Scalar.zero() : q = const Quantity.of(0, Unit.one);
438-
const Scalar.identity() : q = const Quantity.of(1, Unit.one);
439-
Scalar.of(num value, Unit unit) : this(Quantity.of(value, unit));
440-
Scalar.one(num value) : this._(qty(value, Unit.one));
441-
Scalar.percent(num value) : this._(qty(value, percent));
442-
Scalar.perMille(num value) : this._(qty(value, perMille));
443-
Scalar.partsPerMillion(num value) : this._(qty(value, partsPerMillion));
444-
Scalar.partsPerBillion(num value) : this._(qty(value, partsPerBillion));
445-
446-
/// Adds two scalars, converting the addend to the units of this scalar.
424+
/// [scalar] must be a scalar [Quantity] or a [num].
447425
///
448-
/// [addend] may be a [Quantity] or a raw [num].
449-
Scalar operator +(Object addend) => q + numToScalar(addend) as Scalar;
450-
451-
/// Subtracts two scalars, converting the subtrahend to the units of this scalar.
452-
///
453-
/// [subtrahend] may be a [Quantity] or a raw [num].
454-
Scalar operator -(Object subtrahend) => q - numToScalar(subtrahend) as Scalar;
455-
456-
Scalar operator ^(Object exponent) => q ^ exponent as Scalar;
457-
458-
Scalar inverse() => q.inverse() as Scalar;
459-
Scalar squared() => this ^ 2;
460-
Scalar cubed() => this ^ 3;
461-
Scalar sqrt() => this ^ (0.5);
462-
Scalar cbrt() => this ^ (1 / 3);
463-
464-
/// Whether this scalar is numerically smaller than [other] in common units.
465-
///
466-
/// [other] may be a [Quantity] or a raw [num].
467-
bool operator <(Object other) => q < numToScalar(other);
468-
469-
/// Whether this scalar is numerically smaller than or equal to [other] in common units.
470-
///
471-
/// [other] may be a [Quantity] or a raw [num].
472-
bool operator <=(Object other) => q <= numToScalar(other);
473-
474-
/// Whether this scalar is numerically larger than [other] in common units.
475-
///
476-
/// [other] may be a [Quantity] or a raw [num].
477-
bool operator >(Object other) => q > numToScalar(other);
478-
479-
/// Whether this scalar is numerically larger than or equal to [other] in common units.
480-
///
481-
/// [other] may be a [Quantity] or a raw [num].
482-
bool operator >=(Object other) => q >= numToScalar(other);
426+
/// Unlike [operator *], this operation is guaranteed to return the same type [T].
427+
T scaled(Object scalar) => q.scaled(scalar) as T;
483428
}

0 commit comments

Comments
 (0)