Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frequency Enhancements #213

Merged
merged 2 commits into from
Apr 9, 2017
Merged

Frequency Enhancements #213

merged 2 commits into from
Apr 9, 2017

Conversation

garyKeorkunian
Copy link
Contributor

@garyKeorkunian garyKeorkunian commented Mar 30, 2017

Added /(Time) and per(Time) to Squantified numbers to support expression like:

val f: Frequency = 1000 / second
val f: Frequency = 1000 per second

Added *(Frequency) to TimeIntegral to support conversions like:

val dr: DataRate = 1000.bytes * 10/second

Added *(TimeIntegral) to Frequency to support the same conversion with reversed operands:

val dr: DataRate = 10/second * 1000.bytes

However, this last expression returns type Any and needs to be reviewed for ideas on how to fix that before this is merged.

This is intended to close #134

@garyKeorkunian
Copy link
Contributor Author

It may be that the Frequency.*(TimeIntegral) method is too abstract and I'll need to define a method for each TimeIntegral in the libary ....

class Frequency(...) {
   ...
   def *(that: Length): Velocity = that * this
   def *(that: Velocity): Acceleration = that * this
   def *(that: Information): DataRate = that * this
   // etc ...
}

It would be nice if the TimeIntegral/Derivative abstraction could handle that, but maybe not.

Thoughts?

@garyKeorkunian
Copy link
Contributor Author

I replaced the Frequency * TimeIntegral code, which was limited, with explicit methods for each defined TimeIntegral. This achieves the API requirement, but with a bit more code.

This could be improved in the future, but this PR should be mergeable as is - pending review.

Copy link
Collaborator

@derekmorr derekmorr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few small issues, but this look good.

@@ -26,6 +30,36 @@ final class Frequency private (val value: Double, val unit: FrequencyUnit)
protected[squants] def timeIntegrated = Each(toHertz)
protected[squants] def time = Seconds(1)

// Below are two failed attempts to invert the TimeIntegral * Frequency method to support Frequency * TimeIntegral
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove the comments from lines 33 - 44 into the PR. I'd like to preserve them, but I don't think they need to be in the source.

@@ -10,7 +10,7 @@ package squants

import org.scalatest.{ FlatSpec, Matchers }
import squants.thermal.{ Celsius, Fahrenheit }
import squants.time.Hours
import squants.time.{ Hours, Hertz }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - Hertz should be before Hours to keep imports alphabetized.

@derekmorr
Copy link
Collaborator

I agree spelling out the specific types is sub-optimal, but at least we're type safe. We might be able to implement it more generically in the future at the cost of binary compatibility.

With this new syntax, we should update the README. I had removed this syntax in #202 a few months ago. Can you update shared/src/main/tut/README.me and readd

val freq = 60 / second

example in the "Implicit conversion support for using Double on the left side of multiplication" section (which we probably should rename now).

(this was the original line https://github.com/typelevel/squants/pull/202/files#diff-04c6e90faac2675aa89e2176d2eec7d8L487)

Hertz(100) * Webers(100) should be(Volts(10000))
Hertz(100) * Kilograms(100) should be(KilogramsPerSecond(10000))
Hertz(100) * NewtonSeconds(100) should be(Newtons(10000))
Hertz(100) * Watts(100) should be(WattsPerHour(10000))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this in WattsPerHour? Shouldn't the unit be watts per second?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Most time derivative relationships are based on the second. Energy/Power/PowerRamp prefer the WattHour, Watt and WattsPerHour units, so the base time is one hour. The new conversion assumed 1 second, which coupled with my blind paste and copy test setup, led to a passing test on a bad conversion. It's fixed up now.

Thanks!

Copy link
Contributor Author

@garyKeorkunian garyKeorkunian Apr 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although WattsPerSecond, which is effectively a joule / sec^2, would be a good addition to library.

README.md Outdated
@@ -788,14 +789,21 @@ scala> val low = 40.dollars / megawattHour
low: squants.market.Price[squants.energy.Energy] = 40.00 USD/1.0 MWh
```

Implicit conversion support for using Double on the left side of multiplication:
Implicit conversion support for using Doubles, Longs and BigDecimals on the left side of multiply and divide operations:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you edited README.md directly. The readme is built via tut now, so these changes will be overwritten on the next build. Can you also update shared/src/main/tut/README.md so they're preserved?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes. Thanks. Fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I noticed is

BigDecimal(1) / hour works in the tut, but
BigDecimal(1) per hour does not: method not defined.

However, both of these are defined in the same implicit class and both work in the console. For the README, I just went back to using the / operator. Any thoughts on that?

@garyKeorkunian garyKeorkunian force-pushed the wip-squantified-divide branch from cc388f5 to b0c14c5 Compare April 6, 2017 13:31
Copy link
Collaborator

@cquiroz cquiroz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks for the PR

def *(that: LuminousEnergy): LuminousFlux = that * this
def *(that: LuminousExposure): Illuminance = that * this
def *(that: MagneticFlux): ElectricPotential = that * this
def *(that: Mass): MassFlow = that * this
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this produce e.g. [kgs/sec]

Copy link
Contributor Author

@garyKeorkunian garyKeorkunian Apr 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will.

[T^-1] * [M] = [M/T]

@garyKeorkunian garyKeorkunian force-pushed the wip-squantified-divide branch 2 times, most recently from 383dbe8 to 954eb6a Compare April 7, 2017 00:18
Added /(Time) and per(Time) to Squantified numbers to support expression like:

val f: Frequency = 1000 / second

Added *(Frequency) to TimeIntegral to support conversions like:

val dr: DataRate = 1000.bytes * 10/second

Added *(TimeIntegral) to Frequency to support the same conversion in with reversed operands:

val dr: DataRate = 10/second * 1000.bytes

However, this returns type Any and needs to be reviewed for ideas on how to fix that.

Added *(TimeIntegral) to Frequency for all currently defined TimeIntegrals

Review updates

* removed extraneous comments
* alphabetized imports
* updated README
* Fixed Power / Energy / Frequency conversions and tests

Review updates

* Update tut/README

* resolved merge conflicts
@garyKeorkunian garyKeorkunian force-pushed the wip-squantified-divide branch from 954eb6a to 78bf5a2 Compare April 7, 2017 00:20
@derekmorr
Copy link
Collaborator

LGTM.

@derekmorr derekmorr merged commit 67e03c0 into master Apr 9, 2017
@derekmorr derekmorr deleted the wip-squantified-divide branch April 22, 2017 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

multiplication with TimeDerivative is not supported
3 participants