diff --git a/src/core/cgs.scala b/src/core/cgs.scala deleted file mode 100644 index 1a1b316..0000000 --- a/src/core/cgs.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* - Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. - - The primary distribution site is: https://propensive.com/ - - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - file except in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the - License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - either express or implied. See the License for the specific language governing permissions - and limitations under the License. -*/ - -package quantitative - -import hypotenuse.* - -import language.experimental.captureChecking - -val Galileo = MetricUnit(0.01*Metre/(Second*Second)) -val Poise = MetricUnit(0.1*Pascal) -val Franklin = MetricUnit(3.34e-10*Coulomb) -val Biot = MetricUnit(10*Ampere) -val Debye = MetricUnit(3.335e-30*Coulomb*Metre) -val Erg = MetricUnit(10e-7*Joule) -val Dyne = MetricUnit(10e-5*Newton) -val Calorie = MetricUnit(4.184*Joule) -val Langley = MetricUnit(41840*Joule/(Metre*Metre)) -val Phot = MetricUnit(10e4*Lux) -val Stokes = MetricUnit(10e-4*Metre*Metre/Second) -val Lambert = MetricUnit((10e4/π)*Candela/(Metre*Metre)) -val Emu = MetricUnit(10e-3*Ampere/(Metre*Metre)) -val Oersted = MetricUnit(79.577*Ampere/Metre) -val Maxwell = MetricUnit(10e-8*Weber) -val Gauss = MetricUnit(10e-4*Tesla) -val Gilbert = MetricUnit(0.796*Ampere) -val Darcy = MetricUnit(0.987e-12*Metre*Metre) -val Barye = MetricUnit(0.1*Pascal) -val Kayser = MetricUnit(100/Second) diff --git a/src/core/conversions.scala b/src/core/conversions.scala deleted file mode 100644 index a3ad0a7..0000000 --- a/src/core/conversions.scala +++ /dev/null @@ -1,210 +0,0 @@ -/* - Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. - - The primary distribution site is: https://propensive.com/ - - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - file except in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the - License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - either express or implied. See the License for the specific language governing permissions - and limitations under the License. -*/ - -package quantitative - -import rudiments.* -import anticipation.* - -import language.experimental.captureChecking - -erased trait Ratio[UnitsType <: Measure, RatioType <: Double & Singleton] - -// Units of length - -trait Points[Power <: Nat] extends Units[Power, Length] -object Points: - given UnitName[Points[1]] = () => "pt".tt - erased given pointsPerMetre: Ratio[Points[-1] & Metres[1], 3.5277777777777776E-4] = ### - -trait Picas[Power <: Nat] extends Units[Power, Length] -object Picas: - given UnitName[Picas[1]] = () => "pc".tt - erased given picasPerMetre: Ratio[Picas[-1] & Metres[1], 0.004233333333333333] = ### - -trait Inches[Power <: Nat] extends Units[Power, Length] -object Inches: - given UnitName[Inches[1]] = () => "in".tt - erased given inchesPerMetre: Ratio[Inches[-1] & Metres[1], 0.0254] = ### - -trait Feet[Power <: Nat] extends Units[Power, Length] -object Feet: - given UnitName[Feet[1]] = () => "ft".tt - erased given feetPerMetre: Ratio[Feet[-1] & Metres[1], 0.3048] = ### - -trait Yards[Power <: Nat] extends Units[Power, Length] -object Yards: - given UnitName[Yards[1]] = () => "yd".tt - erased given yardsPerMetre: Ratio[Yards[-1] & Metres[1], 0.9144] = ### - -trait Miles[Power <: Nat] extends Units[Power, Length] -object Miles: - given UnitName[Miles[1]] = () => "mi".tt - erased given milesPerMetre: Ratio[Miles[-1] & Metres[1], 1609.344] = ### - -trait Lightyears[Power <: Nat] extends Units[Power, Length] -object Lightyears: - given UnitName[Lightyears[1]] = () => "ly".tt - erased given lightYearsPerMetre: Ratio[Lightyears[1] & Metres[-1], 1.057E-16] = ### - -trait NauticalMiles[Power <: Nat] extends Units[Power, Length] -object NauticalMiles: - given UnitName[NauticalMiles[1]] = () => "NM".tt - erased given nauticalMilesPerMetre: Ratio[NauticalMiles[1] & Metres[-1], 5.399568034557236E-4] = - ### - -trait Furlongs[Power <: Nat] extends Units[Power, Length] -object Furlongs: - given UnitName[Furlongs[1]] = () => "fur".tt - erased given metresPerFurlong: Ratio[Metres[1] & Furlongs[-1], 201.168] = ### - -trait Chains[Power <: Nat] extends Units[Power, Length] -object Chains: - given UnitName[Chains[1]] = () => "ch".tt - erased given metresPerChain: Ratio[Metres[1] & Chains[-1], 20.1168] = ### - -val Inch = Quantity[Inches[1]](1.0) -val Foot = Quantity[Feet[1]](1.0) -val Yard = Quantity[Yards[1]](1.0) -val Mile = Quantity[Miles[1]](1.0) -val Lightyear = Quantity[Lightyears[1]](1.0) -val NauticalMile = Quantity[NauticalMiles[1]](1.0) -val Furlong = Quantity[Furlongs[1]](1.0) -val Chain = Quantity[Chains[1]](1.0) - -// Units of Area - -val Are = MetricUnit[Metres[2]](100.0) -val Acre = Furlong*Furlong/10.0 - -// Units of Volume - -val Litre = MetricUnit[Metres[3]](0.001) -val FluidOunce = Milli(Litre)*28.4130625 -val Pint = Milli(Litre)*568.26125 -val Quart = Milli(Litre)*1136.5225 -val Gallon = Milli(Litre)*4546.09 - -// Units of Mass - -trait Grains[Power <: Nat] extends Units[Power, Mass] -object Grains: - given UnitName[Grains[1]] = () => Text("gr") - erased given kilogramsPerGrain: Ratio[Kilograms[1] & Grains[-1], 0.0000647989] = ### - -trait Drams[Power <: Nat] extends Units[Power, Mass] -object Drams: - given UnitName[Drams[1]] = () => Text("dr") - erased given kilogramsPerDram: Ratio[Kilograms[1] & Drams[-1], 0.00177184375] = ### - -trait Ounces[Power <: Nat] extends Units[Power, Mass] -object Ounces: - given UnitName[Ounces[1]] = () => Text("oz") - erased given kilogramsPerOunce: Ratio[Kilograms[1] & Ounces[-1], 0.0283495] = ### - -trait Pounds[Power <: Nat] extends Units[Power, Mass] -object Pounds: - given UnitName[Pounds[1]] = () => Text("lb") - erased given kilogramsPerPound: Ratio[Kilograms[1] & Pounds[-1], 0.453592] = ### - -trait Stones[Power <: Nat] extends Units[Power, Mass] -object Stones: - given UnitName[Stones[1]] = () => Text("st") - erased given kilogramsPerStone: Ratio[Kilograms[1] & Stones[-1], 6.35029318] = ### - -trait Quarters[Power <: Nat] extends Units[Power, Mass] -object Quarters: - given UnitName[Quarters[1]] = () => Text("qr") - erased given kilogramsPerQuarter: Ratio[Kilograms[1] & Quarters[-1], 12.700586360000001] = ### - -trait Hundredweights[Power <: Nat] extends Units[Power, Mass] -object Hundredweights: - given UnitName[Hundredweights[1]] = () => Text("cwt") - erased given gramsPerHundredweight: Ratio[Kilograms[1] & Hundredweights[-1], 50.80234544] = ### - -trait Tons[Power <: Nat] extends Units[Power, Mass] -object Tons: - erased given gramsPerTon: Ratio[Kilograms[1] & Tons[-1], 1016.0469088] = ### - -val Grain = Quantity[Grains[1]](1.0) -val Ounce = Quantity[Ounces[1]](1.0) -val Pound = Quantity[Pounds[1]](1.0) -val Stone = Quantity[Stones[1]](1.0) -val Hundredweight = Quantity[Hundredweights[1]](1.0) -val Ton = Quantity[Tons[1]](1.0) - -// Units of Time - -val Day = Quantity[Days[1]](1.0) -val Hour = Quantity[Hours[1]](1.0) -val Minute = Quantity[Minutes[1]](1.0) - -trait SiderealDays[Power <: Nat] extends Units[Power, Time] -object SiderealDays: - erased given secondsPerSiderealDay: Ratio[Seconds[1] & SiderealDays[-1], 86164.0905] = ### - -trait Days[Power <: Nat] extends Units[Power, Time] -object Days: - given UnitName[Hours[1]] = () => "d".tt - erased given secondsPerDay: Ratio[Seconds[1] & Days[-1], 86400.0] = ### - -trait Hours[Power <: Nat] extends Units[Power, Time] -object Hours: - given UnitName[Hours[1]] = () => "h".tt - erased given secondsPerHour: Ratio[Seconds[1] & Hours[-1], 3600.0] = ### - -trait Minutes[Power <: Nat] extends Units[Power, Time] -object Minutes: - given UnitName[Minutes[1]] = () => "min".tt - erased given secondsPerMinute: Ratio[Seconds[1] & Minutes[-1], 60.0] = ### - -// Units of Angle - -trait Degrees[Power <: Nat] extends Units[Power, Angle] -object Degrees: - given UnitName[Degrees[1]] = () => Text("°") - erased given degreesPerRadian: Ratio[Degrees[1] & Radians[-1], 57.2957795131] = ### - -trait ArcMinutes[Power <: Nat] extends Units[Power, Angle] -object ArcMinutes: - given UnitName[ArcMinutes[1]] = () => Text("'") - erased given degreesPerRadian: Ratio[ArcMinutes[1] & Radians[-1], 3437.74677078] = ### - -trait ArcSeconds[Power <: Nat] extends Units[Power, Angle] -object ArcSeconds: - given UnitName[ArcSeconds[1]] = () => Text("\"") - erased given degreesPerRadian: Ratio[ArcSeconds[1] & Radians[-1], 206264.806247] = ### - -trait Celsius[Power <: Nat] extends Units[Power, Temperature] -object Celsius: - private final val offset = 273.15 - def apply(value: Double): Quantity[Celsius[1]] = Quantity[Celsius[1]](value + offset) - given UnitsOffset[Celsius[1]] = () => offset - given UnitName[Celsius[1]] = () => Text("°C") - erased given celsiusPerKelvin: Ratio[Celsius[1] & Kelvins[-1], 1.0] = ### - -trait Fahrenheit[Power <: Nat] extends Units[Power, Temperature] -object Fahrenheit: - private final val offset = 459.67 - def apply(value: Double): Quantity[Fahrenheit[1]] = Quantity[Fahrenheit[1]](value + offset) - given UnitsOffset[Fahrenheit[1]] = () => offset - given UnitName[Fahrenheit[1]] = () => Text("°F") - erased given fahrenheitPerKelvin: Ratio[Fahrenheit[1] & Kelvins[-1], 1.8] = ### - -trait Rankines[Power <: Nat] extends Units[Power, Temperature] -object Rankines: - given UnitName[Rankines[1]] = () => Text("°R") - erased given rankinesPerKelvin: Ratio[Rankines[1] & Kelvins[-1], 1.8] = ### diff --git a/src/core/quantifiable.scala b/src/core/quantifiable.scala deleted file mode 100644 index a0c6f69..0000000 --- a/src/core/quantifiable.scala +++ /dev/null @@ -1,81 +0,0 @@ -/* - Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. - - The primary distribution site is: https://propensive.com/ - - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this - file except in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the - License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - either express or implied. See the License for the specific language governing permissions - and limitations under the License. -*/ - -package quantitative - -import rudiments.* -import gossamer.* -import anticipation.* -import symbolism.* - -import language.experimental.captureChecking -import language.implicitConversions - -trait Quantifiable[QuantityType, UnitsType <: Units[?, ?]]: - extension (value: QuantityType) def quantify: Quantity[UnitsType] - -extension (value: Double) - @targetName("times") - infix def * [UnitsType <: Measure](quantity: Quantity[UnitsType]): Quantity[UnitsType] = - quantity*value - - @targetName("divide") - transparent inline infix def / [UnitsType <: Measure](quantity: Quantity[UnitsType]): Any = - ((1.0/value)*quantity).invert - -extension [UnitsType <: Measure](inline quantity: Quantity[UnitsType]) - @targetName("plus") - transparent inline infix def + [UnitsType2 <: Measure](quantity2: Quantity[UnitsType2]): Any = - ${Quantitative.add[UnitsType, UnitsType2]('quantity, 'quantity2, '{false})} - - @targetName("minus") - transparent inline infix def - [UnitsType2 <: Measure](quantity2: Quantity[UnitsType2]): Any = - ${Quantitative.add[UnitsType, UnitsType2]('quantity, 'quantity2, '{true})} - - transparent inline def invert: Any = Quantity[Measure](1.0)/quantity - - transparent inline def in[UnitsType2[power <: Nat] <: Units[power, ?]]: Any = - ${Quantitative.norm[UnitsType, UnitsType2]('quantity)} - - @targetName("times2") - transparent inline infix def * [UnitsType2 <: Measure](inline quantity2: Quantity[UnitsType2]) - : Any = - - ${Quantitative.multiply[UnitsType, UnitsType2]('quantity, 'quantity2, false)} - - @targetName("times3") - transparent inline infix def * [UnitsType2 <: Measure](inline double: Double): Any = - quantity*Quantity(double) - - @targetName("divide2") - transparent inline infix def / [UnitsType2 <: Measure](inline quantity2: Quantity[UnitsType2]) - : Any = - - ${Quantitative.multiply[UnitsType, UnitsType2]('quantity, 'quantity2, true)} - - @targetName("divide3") - transparent inline infix def / [UnitsType2 <: Measure](inline double: Double): Any = - quantity/Quantity(double) - - inline def sqrt(using root: RootOperator[2, Quantity[UnitsType]]): root.Result = - root.root(quantity) - - inline def cbrt(using root: RootOperator[3, Quantity[UnitsType]]): root.Result = - root.root(quantity) - - inline def units: Map[Text, Int] = ${Quantitative.collectUnits[UnitsType]} - inline def render(using Decimalizer): Text = t"${quantity.value} ${Quantity.renderUnits(units)}" - inline def dimension: Text = ${Quantitative.describe[UnitsType]} \ No newline at end of file diff --git a/src/core/derived.scala b/src/core/quantitative.ArcMinutes.scala similarity index 51% rename from src/core/derived.scala rename to src/core/quantitative.ArcMinutes.scala index 21db672..06c3766 100644 --- a/src/core/derived.scala +++ b/src/core/quantitative.ArcMinutes.scala @@ -18,21 +18,11 @@ package quantitative import language.experimental.captureChecking -val Hertz = MetricUnit(1.0/Second) -val Newton = MetricUnit(Metre*Kilo(Gram)/(Second*Second)) -val Pascal = MetricUnit(Newton/(Metre*Metre)) -val Joule = MetricUnit(Newton*Metre) -val Watt = MetricUnit(Joule/Second) -val Coulomb = MetricUnit(Second*Ampere) -val Volt = MetricUnit(Watt/Ampere) -val Farad = MetricUnit(Coulomb/Volt) -val Ohm = MetricUnit(Volt/Ampere) -val Siemens = MetricUnit(Ampere/Volt) -val Weber = MetricUnit(Volt*Second) -val Tesla = MetricUnit(Weber/(Metre*Metre)) -val Henry = MetricUnit(Weber/Ampere) -val Lux = MetricUnit(Candela/(Metre*Metre)) -val Becquerel = MetricUnit(1.0/Second) -val Gray = MetricUnit(Joule/Kilo(Gram)) -val Sievert = MetricUnit(Joule/Kilo(Gram)) -val Katal = MetricUnit(Mole/Second) +import anticipation.* +import rudiments.* + +trait ArcMinutes[Power <: Nat] extends Units[Power, Angle] + +object ArcMinutes: + given UnitName[ArcMinutes[1]] = () => "'".tt + erased given degreesPerRadian: Ratio[ArcMinutes[1] & Radians[-1], 3437.74677078] = ### diff --git a/src/core/quantitative.ArcSeconds.scala b/src/core/quantitative.ArcSeconds.scala new file mode 100644 index 0000000..c356b48 --- /dev/null +++ b/src/core/quantitative.ArcSeconds.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait ArcSeconds[Power <: Nat] extends Units[Power, Angle] + +object ArcSeconds: + given UnitName[ArcSeconds[1]] = () => "\"".tt + erased given degreesPerRadian: Ratio[ArcSeconds[1] & Radians[-1], 206264.806247] = ### diff --git a/src/core/quantitative.Celsius.scala b/src/core/quantitative.Celsius.scala new file mode 100644 index 0000000..ea5800e --- /dev/null +++ b/src/core/quantitative.Celsius.scala @@ -0,0 +1,31 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Celsius[Power <: Nat] extends Units[Power, Temperature] + +object Celsius: + private final val offset = 273.15 + def apply(value: Double): Quantity[Celsius[1]] = Quantity[Celsius[1]](value + offset) + given UnitsOffset[Celsius[1]] = () => offset + given UnitName[Celsius[1]] = () => "°C".tt + erased given celsiusPerKelvin: Ratio[Celsius[1] & Kelvins[-1], 1.0] = ### diff --git a/src/core/quantitative.Chains.scala b/src/core/quantitative.Chains.scala new file mode 100644 index 0000000..1b0cd5b --- /dev/null +++ b/src/core/quantitative.Chains.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Chains[Power <: Nat] extends Units[Power, Length] + +object Chains: + given UnitName[Chains[1]] = () => "ch".tt + erased given metresPerChain: Ratio[Metres[1] & Chains[-1], 20.1168] = ### diff --git a/src/core/quantitative.Days.scala b/src/core/quantitative.Days.scala new file mode 100644 index 0000000..cf0ed5e --- /dev/null +++ b/src/core/quantitative.Days.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Days[Power <: Nat] extends Units[Power, Time] + +object Days: + given UnitName[Hours[1]] = () => "d".tt + erased given secondsPerDay: Ratio[Seconds[1] & Days[-1], 86400.0] = ### diff --git a/src/core/quantitative.Degrees.scala b/src/core/quantitative.Degrees.scala new file mode 100644 index 0000000..90e1e7e --- /dev/null +++ b/src/core/quantitative.Degrees.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Degrees[Power <: Nat] extends Units[Power, Angle] + +object Degrees: + given UnitName[Degrees[1]] = () => "°".tt + erased given degreesPerRadian: Ratio[Degrees[1] & Radians[-1], 57.2957795131] = ### diff --git a/src/core/constants.scala b/src/core/quantitative.Dimension.scala similarity index 59% rename from src/core/constants.scala rename to src/core/quantitative.Dimension.scala index 87af532..d8f5517 100644 --- a/src/core/constants.scala +++ b/src/core/quantitative.Dimension.scala @@ -16,18 +16,26 @@ package quantitative +import language.implicitConversions +import language.experimental.captureChecking + +import scala.quoted.* + +import gossamer.* +import rudiments.* +import anticipation.* import hypotenuse.* +import symbolism.* +import spectacular.* -import language.experimental.captureChecking +trait Dimension -package constants: - val SpeedOfLightInVacuum = 299792458*Metre/Second - val MagneticConstant = 4*π*(10e-7)*Newton/(Ampere*Ampere) - val ElectricConstant = 8.854187817e-12*Farad/Metre - val CharacteristicImpedanceOfVacuum = 376.730313461*Ohm - val PlanckConstant = 6.62607015e-34*Metre*Metre*Kilo(Gram)/Second - val GravitationalConstant = 6.67430e-11*Newton/Metre*Metre/Kilo(Gram)/Kilo(Gram) - val ElementaryCharge = 1.602176634e-19*Coulomb - val AvogadroConstant = 6.02214076e23/Mole - val BoltzmannConstant = 1.380649e-13*Joule/Kelvin +erased trait Length extends Dimension +erased trait Mass extends Dimension +erased trait Time extends Dimension +erased trait Current extends Dimension +erased trait Luminosity extends Dimension +erased trait Temperature extends Dimension +erased trait AmountOfSubstance extends Dimension +erased trait Angle extends Dimension diff --git a/src/core/quantitative.Drams.scala b/src/core/quantitative.Drams.scala new file mode 100644 index 0000000..3e47f5c --- /dev/null +++ b/src/core/quantitative.Drams.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Drams[Power <: Nat] extends Units[Power, Mass] + +object Drams: + given UnitName[Drams[1]] = () => "dr".tt + erased given kilogramsPerDram: Ratio[Kilograms[1] & Drams[-1], 0.00177184375] = ### diff --git a/src/core/quantitative.Fahrenheit.scala b/src/core/quantitative.Fahrenheit.scala new file mode 100644 index 0000000..5874f30 --- /dev/null +++ b/src/core/quantitative.Fahrenheit.scala @@ -0,0 +1,31 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Fahrenheit[Power <: Nat] extends Units[Power, Temperature] + +object Fahrenheit: + private final val offset = 459.67 + def apply(value: Double): Quantity[Fahrenheit[1]] = Quantity[Fahrenheit[1]](value + offset) + given UnitsOffset[Fahrenheit[1]] = () => offset + given UnitName[Fahrenheit[1]] = () => "°F".tt + erased given fahrenheitPerKelvin: Ratio[Fahrenheit[1] & Kelvins[-1], 1.8] = ### diff --git a/src/core/quantitative.Feet.scala b/src/core/quantitative.Feet.scala new file mode 100644 index 0000000..d96db9a --- /dev/null +++ b/src/core/quantitative.Feet.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Feet[Power <: Nat] extends Units[Power, Length] + +object Feet: + given UnitName[Feet[1]] = () => "ft".tt + erased given feetPerMetre: Ratio[Feet[-1] & Metres[1], 0.3048] = ### diff --git a/src/core/quantitative.Furlongs.scala b/src/core/quantitative.Furlongs.scala new file mode 100644 index 0000000..7221420 --- /dev/null +++ b/src/core/quantitative.Furlongs.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Furlongs[Power <: Nat] extends Units[Power, Length] + +object Furlongs: + given UnitName[Furlongs[1]] = () => "fur".tt + erased given metresPerFurlong: Ratio[Metres[1] & Furlongs[-1], 201.168] = ### diff --git a/src/core/quantitative.Grains.scala b/src/core/quantitative.Grains.scala new file mode 100644 index 0000000..6c3351d --- /dev/null +++ b/src/core/quantitative.Grains.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Grains[Power <: Nat] extends Units[Power, Mass] + +object Grains: + given UnitName[Grains[1]] = () => "gr".tt + erased given kilogramsPerGrain: Ratio[Kilograms[1] & Grains[-1], 0.0000647989] = ### diff --git a/src/core/quantitative.Hours.scala b/src/core/quantitative.Hours.scala new file mode 100644 index 0000000..6884874 --- /dev/null +++ b/src/core/quantitative.Hours.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Hours[Power <: Nat] extends Units[Power, Time] + +object Hours: + given UnitName[Hours[1]] = () => "h".tt + erased given secondsPerHour: Ratio[Seconds[1] & Hours[-1], 3600.0] = ### diff --git a/src/core/quantitative.Hundredweights.scala b/src/core/quantitative.Hundredweights.scala new file mode 100644 index 0000000..986878b --- /dev/null +++ b/src/core/quantitative.Hundredweights.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Hundredweights[Power <: Nat] extends Units[Power, Mass] + +object Hundredweights: + given UnitName[Hundredweights[1]] = () => "cwt".tt + erased given gramsPerHundredweight: Ratio[Kilograms[1] & Hundredweights[-1], 50.80234544] = ### diff --git a/src/core/quantitative.Inches.scala b/src/core/quantitative.Inches.scala new file mode 100644 index 0000000..a96af53 --- /dev/null +++ b/src/core/quantitative.Inches.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Inches[Power <: Nat] extends Units[Power, Length] + +object Inches: + given UnitName[Inches[1]] = () => "in".tt + erased given inchesPerMetre: Ratio[Inches[-1] & Metres[1], 0.0254] = ### diff --git a/src/core/quantitative.Lightyears.scala b/src/core/quantitative.Lightyears.scala new file mode 100644 index 0000000..a20f675 --- /dev/null +++ b/src/core/quantitative.Lightyears.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Lightyears[Power <: Nat] extends Units[Power, Length] + +object Lightyears: + given UnitName[Lightyears[1]] = () => "ly".tt + erased given lightYearsPerMetre: Ratio[Lightyears[1] & Metres[-1], 1.057E-16] = ### diff --git a/src/core/quantitative.Measure.scala b/src/core/quantitative.Measure.scala new file mode 100644 index 0000000..e6b7b1f --- /dev/null +++ b/src/core/quantitative.Measure.scala @@ -0,0 +1,21 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +trait Measure diff --git a/src/core/prefixes.scala b/src/core/quantitative.MetricPrefix.scala similarity index 100% rename from src/core/prefixes.scala rename to src/core/quantitative.MetricPrefix.scala index 5763f14..a27b129 100644 --- a/src/core/prefixes.scala +++ b/src/core/quantitative.MetricPrefix.scala @@ -16,10 +16,10 @@ package quantitative -import hypotenuse.* - import language.experimental.captureChecking +import hypotenuse.* + class MetricPrefix(val name: String, val symbol: String, val exponent: Int, val base: 2 | 10): def apply[UnitsType <: Measure](unit: MetricUnit[UnitsType]): Quantity[UnitsType] = Quantity(unit*Quantity(base**exponent)) diff --git a/src/core/quantitative.Miles.scala b/src/core/quantitative.Miles.scala new file mode 100644 index 0000000..2421249 --- /dev/null +++ b/src/core/quantitative.Miles.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Miles[Power <: Nat] extends Units[Power, Length] + +object Miles: + given UnitName[Miles[1]] = () => "mi".tt + erased given milesPerMetre: Ratio[Miles[-1] & Metres[1], 1609.344] = ### diff --git a/src/core/quantitative.Minutes.scala b/src/core/quantitative.Minutes.scala new file mode 100644 index 0000000..e023711 --- /dev/null +++ b/src/core/quantitative.Minutes.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Minutes[Power <: Nat] extends Units[Power, Time] + +object Minutes: + given UnitName[Minutes[1]] = () => "min".tt + erased given secondsPerMinute: Ratio[Seconds[1] & Minutes[-1], 60.0] = ### diff --git a/src/core/quantitative.NauticalMiles.scala b/src/core/quantitative.NauticalMiles.scala new file mode 100644 index 0000000..4bf678a --- /dev/null +++ b/src/core/quantitative.NauticalMiles.scala @@ -0,0 +1,29 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait NauticalMiles[Power <: Nat] extends Units[Power, Length] + +object NauticalMiles: + given UnitName[NauticalMiles[1]] = () => "NM".tt + erased given nauticalMilesPerMetre: Ratio[NauticalMiles[1] & Metres[-1], 5.399568034557236E-4] = + ### diff --git a/src/core/quantitative.Ounces.scala b/src/core/quantitative.Ounces.scala new file mode 100644 index 0000000..451b07a --- /dev/null +++ b/src/core/quantitative.Ounces.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Ounces[Power <: Nat] extends Units[Power, Mass] + +object Ounces: + given UnitName[Ounces[1]] = () => "oz".tt + erased given kilogramsPerOunce: Ratio[Kilograms[1] & Ounces[-1], 0.0283495] = ### diff --git a/src/core/quantify.scala b/src/core/quantitative.PhysicalQuantity.scala similarity index 59% rename from src/core/quantify.scala rename to src/core/quantitative.PhysicalQuantity.scala index b0ff42a..7d97995 100644 --- a/src/core/quantify.scala +++ b/src/core/quantitative.PhysicalQuantity.scala @@ -28,18 +28,6 @@ import scala.quoted.* import language.implicitConversions import language.experimental.captureChecking -trait Dimension - -erased trait Length extends Dimension -erased trait Mass extends Dimension -erased trait Time extends Dimension -erased trait Current extends Dimension -erased trait Luminosity extends Dimension -erased trait Temperature extends Dimension -erased trait AmountOfSubstance extends Dimension - -erased trait Angle extends Dimension - erased trait PhysicalQuantity[DimensionType <: Units[?, ?], LabelType <: Label]() object PhysicalQuantity: @@ -50,11 +38,11 @@ object PhysicalQuantity: erased given current: PhysicalQuantity[Units[1, Current], "current"] = ### erased given temperature: PhysicalQuantity[Units[1, Temperature], "temperature"] = ### erased given luminosity: PhysicalQuantity[Units[1, Luminosity], "luminosity"] = ### - + erased given angle: PhysicalQuantity[Units[1, Angle], "angle"] = ### - + // derived units from https://en.wikipedia.org/wiki/List_of_physical_quantities - + type ElectricalConductivity = Units[-3, Length] & Units[-1, Mass] & Units[3, Time] & Units[2, Current] type Permittivity = Units[-3, Length] & Units[-1, Mass] & Units[4, Time] & Units[2, Current] type ReactionRate = Units[-3, Length] & Units[-1, Time] & Units[1, AmountOfSubstance] @@ -106,10 +94,10 @@ object PhysicalQuantity: type Inductance = Units[2, Length] & Units[1, Mass] & Units[-2, Time] & Units[-2, Current] type MagneticFlux = Units[2, Length] & Units[1, Mass] & Units[-2, Time] & Units[-1, Current] type Entropy = Units[2, Length] & Units[1, Mass] & Units[-2, Time] & Units[-1, Temperature] - + type MolarEntropy = Units[2, Length] & Units[1, Mass] & Units[-2, Time] & Units[-1, Temperature] & Units[-1, AmountOfSubstance] - + type ChemicalPotential = Units[2, Length] & Units[1, Mass] & Units[-2, Time] & Units[-1, AmountOfSubstance] type Energy = Units[2, Length] & Units[1, Mass] & Units[-2, Time] type Spin = Units[2, Length] & Units[1, Mass] & Units[-1, Time] @@ -118,7 +106,7 @@ object PhysicalQuantity: type VolumetricFlowRate = Units[3, Length] & Units[-1, Time] type Volume = Units[3, Length] type ElectricalResistivity = Units[3, Length] & Units[1, Mass] & Units[-3, Time] & Units[-2, Current] - + erased given absement: PhysicalQuantity[Absement, "absement"] = ### erased given absorbedDoseRate: PhysicalQuantity[AbsorbedDoseRate, "absorbed dose rate"] = ### erased given acceleration: PhysicalQuantity[Acceleration, "acceleration"] = ### @@ -178,188 +166,7 @@ object PhysicalQuantity: erased given specificHeatCapacity: PhysicalQuantity[SpecificHeatCapacity, "specific heat capacity"] = ### erased given thermalConductivity: PhysicalQuantity[ThermalConductivity, "thermal conductivity"] = ### erased given volumetricFlowRate: PhysicalQuantity[VolumetricFlowRate, "volumetric flow rate"] = ### - + erased given electricDisplacementField : PhysicalQuantity[ElectricDisplacementField, "electric displacement field"] = ### - -sealed trait Measure - -trait Units[PowerType <: Nat, DimensionType <: Dimension] extends Measure - -erased trait Metres[Power <: Nat] extends Units[Power, Length] -erased trait Kilograms[Power <: Nat] extends Units[Power, Mass] -erased trait Candelas[Power <: Nat] extends Units[Power, Luminosity] -erased trait Moles[Power <: Nat] extends Units[Power, AmountOfSubstance] -erased trait Amperes[Power <: Nat] extends Units[Power, Current] -erased trait Kelvins[Power <: Nat] extends Units[Power, Temperature] -erased trait Seconds[Power <: Nat] extends Units[Power, Time] - -erased trait Radians[Power <: Nat] extends Units[Power, Angle] - -trait UnitName[-ValueType]: - def siPrefix: MetricPrefix = NoPrefix - def name(): Text - def text: Text = t"${siPrefix.symbol}${name()}" - -object UnitName: - given UnitName[Metres[1]] = () => t"m" - given UnitName[Candelas[1]] = () => t"cd" - given UnitName[Moles[1]] = () => t"mol" - given UnitName[Amperes[1]] = () => t"A" - given UnitName[Kelvins[1]] = () => t"K" - given UnitName[Seconds[1]] = () => t"s" - - given UnitName[Radians[1]] = () => t"rad" - - given UnitName[Kilograms[1]] with - override def siPrefix: MetricPrefix = Kilo - def name(): Text = t"g" - -trait PrincipalUnit[DimensionType <: Dimension, UnitType[_ <: Nat] <: Measure]() - -object PrincipalUnit: - given length: PrincipalUnit[Length, Metres]() - given mass: PrincipalUnit[Mass, Kilograms]() - given time: PrincipalUnit[Time, Seconds]() - given current: PrincipalUnit[Current, Amperes]() - given luminosity: PrincipalUnit[Luminosity, Candelas]() - given temperature: PrincipalUnit[Temperature, Kelvins]() - given amountOfSubstance: PrincipalUnit[AmountOfSubstance, Moles]() - - given angle: PrincipalUnit[Angle, Radians]() - -trait SubstituteUnits[UnitsType <: Measure](val name: Text) - -object SubstituteUnits: - given joules: SubstituteUnits[Kilograms[1] & Metres[2] & Seconds[-2]](t"J") - given newtons: SubstituteUnits[Kilograms[1] & Metres[1] & Seconds[-2]](t"N") - -trait UnitsOffset[UnitsType <: Measure]: - def value(): Double - -object Quantitative extends Quantitative2: - opaque type Quantity[UnitsType <: Measure] = Double - opaque type MetricUnit[UnitsType <: Measure] <: Quantity[UnitsType] = Double - - extension [UnitsType <: Measure](quantity: Quantity[UnitsType]) - def underlying: Double = quantity - - inline def value: Double = compiletime.summonFrom: - case unitsOffset: UnitsOffset[UnitsType] => quantity - unitsOffset.value() - case _ => quantity - - object MetricUnit: - erased given underlying[UnitsType <: Measure]: Underlying[MetricUnit[UnitsType], Double] = ### - def apply[UnitsType <: Measure](value: Double): MetricUnit[UnitsType] = value - - @targetName("makeDerivedUnit") - def apply[UnitsType <: Measure](value: Quantity[UnitsType]): MetricUnit[UnitsType] = value - - object Quantity: - erased given underlying[UnitsType <: Measure]: Underlying[Quantity[UnitsType], Double] = ### - erased given [UnitsType <: Measure]: CanEqual[Quantity[UnitsType], Quantity[UnitsType]] = ### - - given genericDuration: GenericDuration with - type Self = Quantity[Seconds[1]] - def milliseconds(quantity: Quantity[Seconds[1]]): Long = (quantity*1000.0).toLong - - given specificDuration: SpecificDuration with - type Self = Quantity[Seconds[1]] - def duration(long: Long): Quantity[Seconds[1]] = Quantity(long/1000.0) - - transparent inline given add[LeftType <: Measure, RightType <: Measure] - : AddOperator[Quantity[LeftType], Quantity[RightType]] = - - ${Quantitative.addTypeclass[LeftType, RightType]} - - transparent inline given sub[LeftType <: Measure, RightType <: Measure] - : SubOperator[Quantity[LeftType], Quantity[RightType]] = - - ${Quantitative.subTypeclass[LeftType, RightType]} - - transparent inline given mul[LeftType <: Measure, RightType <: Measure] - : MulOperator[Quantity[LeftType], Quantity[RightType]] = - - ${Quantitative.mulTypeclass[LeftType, RightType]} - - given mul2[LeftType <: Measure]: MulOperator[Quantity[LeftType], Double] with - type Result = Quantity[LeftType] - inline def mul(left: Quantity[LeftType], right: Double): Quantity[LeftType] = left*right - - transparent inline given div[LeftType <: Measure, RightType <: Measure] - : DivOperator[Quantity[LeftType], Quantity[RightType]] = - - ${Quantitative.divTypeclass[LeftType, RightType]} - - given div2[LeftType <: Measure]: DivOperator[Quantity[LeftType], Double] with - type Result = Quantity[LeftType] - inline def div(left: Quantity[LeftType], right: Double): Quantity[LeftType] = left/right - - transparent inline given squareRoot[ValueType <: Measure] - : RootOperator[2, Quantity[ValueType]] = - ${Quantitative.sqrtTypeclass[ValueType]} - - transparent inline given cubeRoot[ValueType <: Measure]: RootOperator[3, Quantity[ValueType]] = - ${Quantitative.cbrtTypeclass[ValueType]} - - inline def apply[UnitsType <: Measure](value: Double): Quantity[UnitsType] = value - given convertDouble[UnitsType <: Measure]: Conversion[Double, Quantity[UnitsType]] = Quantity(_) - - given convertInt[UnitsType <: Measure]: Conversion[Int, Quantity[UnitsType]] = - int => Quantity(int.toDouble) - - given inequality[UnitsType <: Measure, UnitsType2 <: Measure] - : Inequality[Quantity[UnitsType], Quantity[UnitsType2]] with - - inline def compare - (inline left: Quantity[UnitsType], - inline right: Quantity[UnitsType2], - inline strict: Boolean, - inline greaterThan: Boolean) - : Boolean = - - ${Quantitative.greaterThan[UnitsType, UnitsType2]('left, 'right, 'strict, 'greaterThan)} - - - inline given [UnitsType <: Measure](using Decimalizer): Show[Quantity[UnitsType]] = - new Show[Quantity[UnitsType]]: - def text(value: Quantity[UnitsType]): Text = value.render - - inline given [UnitsType <: Measure](using Decimalizer): Debug[Quantity[UnitsType]] = - new Debug[Quantity[UnitsType]]: - def text(value: Quantity[UnitsType]): Text = value.render - - def renderUnits(units: Map[Text, Int]): Text = - units.to(List).map: (unit, power) => - if power == 1 then unit - else - val exponent: Text = - power.show.mapChars: - case '0' => '⁰' - case '1' => '¹' - case '2' => '²' - case '3' => '³' - case '4' => '⁴' - case '5' => '⁵' - case '6' => '⁶' - case '7' => '⁷' - case '8' => '⁸' - case '9' => '⁹' - case '-' => '¯' - case _ => ' ' - - t"$unit$exponent" - .join(t"·") - -export Quantitative.{Quantity, MetricUnit} - -val Metre: MetricUnit[Metres[1]] = MetricUnit(1) -val Gram: MetricUnit[Kilograms[1]] = MetricUnit(0.001) -val Candela: MetricUnit[Candelas[1]] = MetricUnit(1) -val Mole: MetricUnit[Moles[1]] = MetricUnit(1) -val Ampere: MetricUnit[Amperes[1]] = MetricUnit(1) -val Kelvin: MetricUnit[Kelvins[1]] = MetricUnit(1) -val Second: MetricUnit[Seconds[1]] = MetricUnit(1) - -val Radian: MetricUnit[Radians[1]] = MetricUnit(1) diff --git a/src/core/quantitative.Picas.scala b/src/core/quantitative.Picas.scala new file mode 100644 index 0000000..0061a80 --- /dev/null +++ b/src/core/quantitative.Picas.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Picas[Power <: Nat] extends Units[Power, Length] + +object Picas: + given UnitName[Picas[1]] = () => "pc".tt + erased given picasPerMetre: Ratio[Picas[-1] & Metres[1], 0.004233333333333333] = ### diff --git a/src/core/quantitative.Points.scala b/src/core/quantitative.Points.scala new file mode 100644 index 0000000..d4a6e36 --- /dev/null +++ b/src/core/quantitative.Points.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Points[Power <: Nat] extends Units[Power, Length] + +object Points: + given UnitName[Points[1]] = () => "pt".tt + erased given pointsPerMetre: Ratio[Points[-1] & Metres[1], 3.5277777777777776E-4] = ### diff --git a/src/core/quantitative.Pounds.scala b/src/core/quantitative.Pounds.scala new file mode 100644 index 0000000..c58e6c6 --- /dev/null +++ b/src/core/quantitative.Pounds.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Pounds[Power <: Nat] extends Units[Power, Mass] + +object Pounds: + given UnitName[Pounds[1]] = () => "lb".tt + erased given kilogramsPerPound: Ratio[Kilograms[1] & Pounds[-1], 0.453592] = ### diff --git a/src/core/quantitative.PrincipalUnit.scala b/src/core/quantitative.PrincipalUnit.scala new file mode 100644 index 0000000..a2dbd08 --- /dev/null +++ b/src/core/quantitative.PrincipalUnit.scala @@ -0,0 +1,42 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import gossamer.* +import rudiments.* +import anticipation.* +import hypotenuse.* +import symbolism.* +import spectacular.* + +import scala.quoted.* + +import language.implicitConversions +import language.experimental.captureChecking + +trait PrincipalUnit[DimensionType <: Dimension, UnitType[_ <: Nat] <: Measure]() + +object PrincipalUnit: + given length: PrincipalUnit[Length, Metres]() + given mass: PrincipalUnit[Mass, Kilograms]() + given time: PrincipalUnit[Time, Seconds]() + given current: PrincipalUnit[Current, Amperes]() + given luminosity: PrincipalUnit[Luminosity, Candelas]() + given temperature: PrincipalUnit[Temperature, Kelvins]() + given amountOfSubstance: PrincipalUnit[AmountOfSubstance, Moles]() + + given angle: PrincipalUnit[Angle, Radians]() diff --git a/src/core/quantitative.Quantifiable.scala b/src/core/quantitative.Quantifiable.scala new file mode 100644 index 0000000..2947b43 --- /dev/null +++ b/src/core/quantitative.Quantifiable.scala @@ -0,0 +1,4 @@ +package quantitative + +trait Quantifiable[QuantityType, UnitsType <: Units[?, ?]]: + extension (value: QuantityType) def quantify: Quantity[UnitsType] diff --git a/src/core/quantitative.Quantitative.scala b/src/core/quantitative.Quantitative.scala new file mode 100644 index 0000000..cedfb6f --- /dev/null +++ b/src/core/quantitative.Quantitative.scala @@ -0,0 +1,145 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import gossamer.* +import rudiments.* +import anticipation.* +import hypotenuse.* +import symbolism.* +import spectacular.* + +import scala.quoted.* + +import language.implicitConversions +import language.experimental.captureChecking + +object Quantitative extends Quantitative2: + opaque type Quantity[UnitsType <: Measure] = Double + opaque type MetricUnit[UnitsType <: Measure] <: Quantity[UnitsType] = Double + + extension [UnitsType <: Measure](quantity: Quantity[UnitsType]) + def underlying: Double = quantity + + inline def value: Double = compiletime.summonFrom: + case unitsOffset: UnitsOffset[UnitsType] => quantity - unitsOffset.value() + case _ => quantity + + object MetricUnit: + erased given underlying[UnitsType <: Measure]: Underlying[MetricUnit[UnitsType], Double] = ### + def apply[UnitsType <: Measure](value: Double): MetricUnit[UnitsType] = value + + @targetName("makeDerivedUnit") + def apply[UnitsType <: Measure](value: Quantity[UnitsType]): MetricUnit[UnitsType] = value + + object Quantity: + erased given underlying[UnitsType <: Measure]: Underlying[Quantity[UnitsType], Double] = ### + erased given [UnitsType <: Measure]: CanEqual[Quantity[UnitsType], Quantity[UnitsType]] = ### + + given genericDuration: GenericDuration with + type Self = Quantity[Seconds[1]] + def milliseconds(quantity: Quantity[Seconds[1]]): Long = (quantity*1000.0).toLong + + given specificDuration: SpecificDuration with + type Self = Quantity[Seconds[1]] + def duration(long: Long): Quantity[Seconds[1]] = Quantity(long/1000.0) + + transparent inline given add[LeftType <: Measure, RightType <: Measure] + : AddOperator[Quantity[LeftType], Quantity[RightType]] = + + ${Quantitative.addTypeclass[LeftType, RightType]} + + transparent inline given sub[LeftType <: Measure, RightType <: Measure] + : SubOperator[Quantity[LeftType], Quantity[RightType]] = + + ${Quantitative.subTypeclass[LeftType, RightType]} + + transparent inline given mul[LeftType <: Measure, RightType <: Measure] + : MulOperator[Quantity[LeftType], Quantity[RightType]] = + + ${Quantitative.mulTypeclass[LeftType, RightType]} + + given mul2[LeftType <: Measure]: MulOperator[Quantity[LeftType], Double] with + type Result = Quantity[LeftType] + inline def mul(left: Quantity[LeftType], right: Double): Quantity[LeftType] = left*right + + transparent inline given div[LeftType <: Measure, RightType <: Measure] + : DivOperator[Quantity[LeftType], Quantity[RightType]] = + + ${Quantitative.divTypeclass[LeftType, RightType]} + + given div2[LeftType <: Measure]: DivOperator[Quantity[LeftType], Double] with + type Result = Quantity[LeftType] + inline def div(left: Quantity[LeftType], right: Double): Quantity[LeftType] = left/right + + transparent inline given squareRoot[ValueType <: Measure] + : RootOperator[2, Quantity[ValueType]] = + ${Quantitative.sqrtTypeclass[ValueType]} + + transparent inline given cubeRoot[ValueType <: Measure]: RootOperator[3, Quantity[ValueType]] = + ${Quantitative.cbrtTypeclass[ValueType]} + + inline def apply[UnitsType <: Measure](value: Double): Quantity[UnitsType] = value + given convertDouble[UnitsType <: Measure]: Conversion[Double, Quantity[UnitsType]] = Quantity(_) + + given convertInt[UnitsType <: Measure]: Conversion[Int, Quantity[UnitsType]] = + int => Quantity(int.toDouble) + + given inequality[UnitsType <: Measure, UnitsType2 <: Measure] + : Inequality[Quantity[UnitsType], Quantity[UnitsType2]] with + + inline def compare + (inline left: Quantity[UnitsType], + inline right: Quantity[UnitsType2], + inline strict: Boolean, + inline greaterThan: Boolean) + : Boolean = + + ${Quantitative.greaterThan[UnitsType, UnitsType2]('left, 'right, 'strict, 'greaterThan)} + + + inline given [UnitsType <: Measure](using Decimalizer): Show[Quantity[UnitsType]] = + new Show[Quantity[UnitsType]]: + def text(value: Quantity[UnitsType]): Text = value.render + + inline given [UnitsType <: Measure](using Decimalizer): Debug[Quantity[UnitsType]] = + new Debug[Quantity[UnitsType]]: + def text(value: Quantity[UnitsType]): Text = value.render + + def renderUnits(units: Map[Text, Int]): Text = + units.to(List).map: (unit, power) => + if power == 1 then unit + else + val exponent: Text = + power.show.mapChars: + case '0' => '⁰' + case '1' => '¹' + case '2' => '²' + case '3' => '³' + case '4' => '⁴' + case '5' => '⁵' + case '6' => '⁶' + case '7' => '⁷' + case '8' => '⁸' + case '9' => '⁹' + case '-' => '¯' + case _ => ' ' + + t"$unit$exponent" + .join(t"·") + +export Quantitative.{Quantity, MetricUnit} diff --git a/src/core/quantity.scala b/src/core/quantitative.Quantitative2.scala similarity index 100% rename from src/core/quantity.scala rename to src/core/quantitative.Quantitative2.scala diff --git a/src/core/quantitative.Quarters.scala b/src/core/quantitative.Quarters.scala new file mode 100644 index 0000000..ffe688b --- /dev/null +++ b/src/core/quantitative.Quarters.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Quarters[Power <: Nat] extends Units[Power, Mass] + +object Quarters: + given UnitName[Quarters[1]] = () => "qr".tt + erased given kilogramsPerQuarter: Ratio[Kilograms[1] & Quarters[-1], 12.700586360000001] = ### diff --git a/src/core/quantitative.Rankines.scala b/src/core/quantitative.Rankines.scala new file mode 100644 index 0000000..78114cb --- /dev/null +++ b/src/core/quantitative.Rankines.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Rankines[Power <: Nat] extends Units[Power, Temperature] + +object Rankines: + given UnitName[Rankines[1]] = () => "°R".tt + erased given rankinesPerKelvin: Ratio[Rankines[1] & Kelvins[-1], 1.8] = ### diff --git a/src/core/quantitative.Ratio.scala b/src/core/quantitative.Ratio.scala new file mode 100644 index 0000000..29032d9 --- /dev/null +++ b/src/core/quantitative.Ratio.scala @@ -0,0 +1,24 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import rudiments.* +import anticipation.* + +import language.experimental.captureChecking + +erased trait Ratio[UnitsType <: Measure, RatioType <: Double & Singleton] diff --git a/src/core/quantitative.SiderealDays.scala b/src/core/quantitative.SiderealDays.scala new file mode 100644 index 0000000..b2a14dd --- /dev/null +++ b/src/core/quantitative.SiderealDays.scala @@ -0,0 +1,27 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait SiderealDays[Power <: Nat] extends Units[Power, Time] + +object SiderealDays: + erased given secondsPerSiderealDay: Ratio[Seconds[1] & SiderealDays[-1], 86164.0905] = ### diff --git a/src/core/quantitative.Stones.scala b/src/core/quantitative.Stones.scala new file mode 100644 index 0000000..23cb881 --- /dev/null +++ b/src/core/quantitative.Stones.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Stones[Power <: Nat] extends Units[Power, Mass] + +object Stones: + given UnitName[Stones[1]] = () => "st".tt + erased given kilogramsPerStone: Ratio[Kilograms[1] & Stones[-1], 6.35029318] = ### diff --git a/src/core/quantitative.SubstituteUnits.scala b/src/core/quantitative.SubstituteUnits.scala new file mode 100644 index 0000000..d0cde03 --- /dev/null +++ b/src/core/quantitative.SubstituteUnits.scala @@ -0,0 +1,35 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import gossamer.* +import rudiments.* +import anticipation.* +import hypotenuse.* +import symbolism.* +import spectacular.* + +import scala.quoted.* + +import language.implicitConversions +import language.experimental.captureChecking + +trait SubstituteUnits[UnitsType <: Measure](val name: Text) + +object SubstituteUnits: + given joules: SubstituteUnits[Kilograms[1] & Metres[2] & Seconds[-2]](t"J") + given newtons: SubstituteUnits[Kilograms[1] & Metres[1] & Seconds[-2]](t"N") diff --git a/src/core/quantitative.Tons.scala b/src/core/quantitative.Tons.scala new file mode 100644 index 0000000..e4c2247 --- /dev/null +++ b/src/core/quantitative.Tons.scala @@ -0,0 +1,27 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Tons[Power <: Nat] extends Units[Power, Mass] + +object Tons: + erased given gramsPerTon: Ratio[Kilograms[1] & Tons[-1], 1016.0469088] = ### diff --git a/src/core/quantitative.UnitName.scala b/src/core/quantitative.UnitName.scala new file mode 100644 index 0000000..a6f02da --- /dev/null +++ b/src/core/quantitative.UnitName.scala @@ -0,0 +1,48 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import gossamer.* +import rudiments.* +import anticipation.* +import hypotenuse.* +import symbolism.* +import spectacular.* + +import scala.quoted.* + +import language.implicitConversions +import language.experimental.captureChecking + +trait UnitName[-ValueType]: + def siPrefix: MetricPrefix = NoPrefix + def name(): Text + def text: Text = t"${siPrefix.symbol}${name()}" + +object UnitName: + given UnitName[Metres[1]] = () => t"m" + given UnitName[Candelas[1]] = () => t"cd" + given UnitName[Moles[1]] = () => t"mol" + given UnitName[Amperes[1]] = () => t"A" + given UnitName[Kelvins[1]] = () => t"K" + given UnitName[Seconds[1]] = () => t"s" + + given UnitName[Radians[1]] = () => t"rad" + + given UnitName[Kilograms[1]] with + override def siPrefix: MetricPrefix = Kilo + def name(): Text = t"g" diff --git a/src/core/quantitative.Units.scala b/src/core/quantitative.Units.scala new file mode 100644 index 0000000..d18cf2b --- /dev/null +++ b/src/core/quantitative.Units.scala @@ -0,0 +1,31 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import rudiments.* + +trait Units[PowerType <: Nat, DimensionType <: Dimension] extends Measure + +erased trait Metres[Power <: Nat] extends Units[Power, Length] +erased trait Kilograms[Power <: Nat] extends Units[Power, Mass] +erased trait Candelas[Power <: Nat] extends Units[Power, Luminosity] +erased trait Moles[Power <: Nat] extends Units[Power, AmountOfSubstance] +erased trait Amperes[Power <: Nat] extends Units[Power, Current] +erased trait Kelvins[Power <: Nat] extends Units[Power, Temperature] +erased trait Seconds[Power <: Nat] extends Units[Power, Time] + +erased trait Radians[Power <: Nat] extends Units[Power, Angle] diff --git a/src/core/quantitative.UnitsOffset.scala b/src/core/quantitative.UnitsOffset.scala new file mode 100644 index 0000000..ea3e6c1 --- /dev/null +++ b/src/core/quantitative.UnitsOffset.scala @@ -0,0 +1,32 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import gossamer.* +import rudiments.* +import anticipation.* +import hypotenuse.* +import symbolism.* +import spectacular.* + +import scala.quoted.* + +import language.implicitConversions +import language.experimental.captureChecking + +trait UnitsOffset[UnitsType <: Measure]: + def value(): Double diff --git a/src/core/quantitative.Yards.scala b/src/core/quantitative.Yards.scala new file mode 100644 index 0000000..3002a8b --- /dev/null +++ b/src/core/quantitative.Yards.scala @@ -0,0 +1,28 @@ +/* + Quantitative, version [unreleased]. Copyright 2024 Jon Pretty, Propensive OÜ. + + The primary distribution site is: https://propensive.com/ + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific language governing permissions + and limitations under the License. +*/ + +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import rudiments.* + +trait Yards[Power <: Nat] extends Units[Power, Length] + +object Yards: + given UnitName[Yards[1]] = () => "yd".tt + erased given yardsPerMetre: Ratio[Yards[-1] & Metres[1], 0.9144] = ### diff --git a/src/core/quantitative.scala b/src/core/quantitative.scala new file mode 100644 index 0000000..b62a34f --- /dev/null +++ b/src/core/quantitative.scala @@ -0,0 +1,155 @@ +package quantitative + +import language.experimental.captureChecking + +import anticipation.* +import gossamer.* +import hypotenuse.* +import rudiments.* +import symbolism.* + +val Galileo = MetricUnit(0.01*Metre/(Second*Second)) +val Poise = MetricUnit(0.1*Pascal) +val Franklin = MetricUnit(3.34e-10*Coulomb) +val Biot = MetricUnit(10*Ampere) +val Debye = MetricUnit(3.335e-30*Coulomb*Metre) +val Erg = MetricUnit(10e-7*Joule) +val Dyne = MetricUnit(10e-5*Newton) +val Calorie = MetricUnit(4.184*Joule) +val Langley = MetricUnit(41840*Joule/(Metre*Metre)) +val Phot = MetricUnit(10e4*Lux) +val Stokes = MetricUnit(10e-4*Metre*Metre/Second) +val Lambert = MetricUnit((10e4/π)*Candela/(Metre*Metre)) +val Emu = MetricUnit(10e-3*Ampere/(Metre*Metre)) +val Oersted = MetricUnit(79.577*Ampere/Metre) +val Maxwell = MetricUnit(10e-8*Weber) +val Gauss = MetricUnit(10e-4*Tesla) +val Gilbert = MetricUnit(0.796*Ampere) +val Darcy = MetricUnit(0.987e-12*Metre*Metre) +val Barye = MetricUnit(0.1*Pascal) +val Kayser = MetricUnit(100/Second) + +val Hertz = MetricUnit(1.0/Second) +val Newton = MetricUnit(Metre*Kilo(Gram)/(Second*Second)) +val Pascal = MetricUnit(Newton/(Metre*Metre)) +val Joule = MetricUnit(Newton*Metre) +val Watt = MetricUnit(Joule/Second) +val Coulomb = MetricUnit(Second*Ampere) +val Volt = MetricUnit(Watt/Ampere) +val Farad = MetricUnit(Coulomb/Volt) +val Ohm = MetricUnit(Volt/Ampere) +val Siemens = MetricUnit(Ampere/Volt) +val Weber = MetricUnit(Volt*Second) +val Tesla = MetricUnit(Weber/(Metre*Metre)) +val Henry = MetricUnit(Weber/Ampere) +val Lux = MetricUnit(Candela/(Metre*Metre)) +val Becquerel = MetricUnit(1.0/Second) +val Gray = MetricUnit(Joule/Kilo(Gram)) +val Sievert = MetricUnit(Joule/Kilo(Gram)) +val Katal = MetricUnit(Mole/Second) + +extension [UnitsType <: Measure](inline quantity: Quantity[UnitsType]) + @targetName("plus") + transparent inline infix def + [UnitsType2 <: Measure](quantity2: Quantity[UnitsType2]): Any = + ${Quantitative.add[UnitsType, UnitsType2]('quantity, 'quantity2, '{false})} + + @targetName("minus") + transparent inline infix def - [UnitsType2 <: Measure](quantity2: Quantity[UnitsType2]): Any = + ${Quantitative.add[UnitsType, UnitsType2]('quantity, 'quantity2, '{true})} + + transparent inline def invert: Any = Quantity[Measure](1.0)/quantity + + transparent inline def in[UnitsType2[power <: Nat] <: Units[power, ?]]: Any = + ${Quantitative.norm[UnitsType, UnitsType2]('quantity)} + + @targetName("times2") + transparent inline infix def * [UnitsType2 <: Measure](inline quantity2: Quantity[UnitsType2]) + : Any = + + ${Quantitative.multiply[UnitsType, UnitsType2]('quantity, 'quantity2, false)} + + @targetName("times3") + transparent inline infix def * [UnitsType2 <: Measure](inline double: Double): Any = + quantity*Quantity(double) + + @targetName("divide2") + transparent inline infix def / [UnitsType2 <: Measure](inline quantity2: Quantity[UnitsType2]) + : Any = + + ${Quantitative.multiply[UnitsType, UnitsType2]('quantity, 'quantity2, true)} + + @targetName("divide3") + transparent inline infix def / [UnitsType2 <: Measure](inline double: Double): Any = + quantity/Quantity(double) + + inline def sqrt(using root: RootOperator[2, Quantity[UnitsType]]): root.Result = + root.root(quantity) + + inline def cbrt(using root: RootOperator[3, Quantity[UnitsType]]): root.Result = + root.root(quantity) + + inline def units: Map[Text, Int] = ${Quantitative.collectUnits[UnitsType]} + inline def render(using Decimalizer): Text = t"${quantity.value} ${Quantity.renderUnits(units)}" + inline def dimension: Text = ${Quantitative.describe[UnitsType]} + +extension (value: Double) + @targetName("times") + infix def * [UnitsType <: Measure](quantity: Quantity[UnitsType]): Quantity[UnitsType] = + quantity*value + + @targetName("divide") + transparent inline infix def / [UnitsType <: Measure](quantity: Quantity[UnitsType]): Any = + ((1.0/value)*quantity).invert + +package constants: + val SpeedOfLightInVacuum = 299792458*Metre/Second + val MagneticConstant = 4*π*(10e-7)*Newton/(Ampere*Ampere) + val ElectricConstant = 8.854187817e-12*Farad/Metre + val CharacteristicImpedanceOfVacuum = 376.730313461*Ohm + val PlanckConstant = 6.62607015e-34*Metre*Metre*Kilo(Gram)/Second + val GravitationalConstant = 6.67430e-11*Newton/Metre*Metre/Kilo(Gram)/Kilo(Gram) + val ElementaryCharge = 1.602176634e-19*Coulomb + val AvogadroConstant = 6.02214076e23/Mole + val BoltzmannConstant = 1.380649e-13*Joule/Kelvin + +val Metre: MetricUnit[Metres[1]] = MetricUnit(1) +val Gram: MetricUnit[Kilograms[1]] = MetricUnit(0.001) +val Candela: MetricUnit[Candelas[1]] = MetricUnit(1) +val Mole: MetricUnit[Moles[1]] = MetricUnit(1) +val Ampere: MetricUnit[Amperes[1]] = MetricUnit(1) +val Kelvin: MetricUnit[Kelvins[1]] = MetricUnit(1) +val Second: MetricUnit[Seconds[1]] = MetricUnit(1) +val Radian: MetricUnit[Radians[1]] = MetricUnit(1) + +val Inch = Quantity[Inches[1]](1.0) +val Foot = Quantity[Feet[1]](1.0) +val Yard = Quantity[Yards[1]](1.0) +val Mile = Quantity[Miles[1]](1.0) +val Lightyear = Quantity[Lightyears[1]](1.0) +val NauticalMile = Quantity[NauticalMiles[1]](1.0) +val Furlong = Quantity[Furlongs[1]](1.0) +val Chain = Quantity[Chains[1]](1.0) + +val Grain = Quantity[Grains[1]](1.0) +val Ounce = Quantity[Ounces[1]](1.0) +val Pound = Quantity[Pounds[1]](1.0) +val Stone = Quantity[Stones[1]](1.0) +val Hundredweight = Quantity[Hundredweights[1]](1.0) +val Ton = Quantity[Tons[1]](1.0) + +val Day = Quantity[Days[1]](1.0) +val Hour = Quantity[Hours[1]](1.0) +val Minute = Quantity[Minutes[1]](1.0) + +// Units of Area + +val Are = MetricUnit[Metres[2]](100.0) +val Acre = Furlong*Furlong/10.0 + +// Units of Volume + +val Litre = MetricUnit[Metres[3]](0.001) +val FluidOunce = Milli(Litre)*28.4130625 +val Pint = Milli(Litre)*568.26125 +val Quart = Milli(Litre)*1136.5225 +val Gallon = Milli(Litre)*4546.09