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

Angle type #88

Open
karwa opened this issue Dec 27, 2019 · 5 comments
Open

Angle type #88

karwa opened this issue Dec 27, 2019 · 5 comments

Comments

@karwa
Copy link

karwa commented Dec 27, 2019

I wonder if we might rather define our trig functions in terms of an Angle type:

public struct Angle<T: Real> {
  public var radians: T
  public init(radians: T) { self.radians = radians }
  public static func radians(_ val: T) -> Angle<T> { .init(radians: val) }
  
  public var degrees: T { radians * 180 / .pi }
  public init(degrees: T) { self.init(radians: degrees * .pi / 180) }
  public static func degrees(_ val: T) -> Angle<T> { .init(degrees: val) }
}

Browsing SE-0246, this alternative design doesn't seem to have been considered, but I think it would help to make our functions more useful and self-documenting. Depending on what you're doing, it can be more natural to think in terms of degrees rather than radians. In C, people tend to bring these utility functions/macros by themselves, whereas other languages like Java include them as part of the standard library.

The design of the type given above means that creating and consuming an Angle in radians in essentially free.

Clearly, we cannot make this change to the ElementaryFunctions protocol requirements, as we need the conforming type to provide those implementations. However, we can do this for the free functions - either in addition to, or in place of the regular functions which take a <T:ElementaryFunctions> argument.

@stephentyrone
Copy link
Member

stephentyrone commented Dec 28, 2019

I've thought about this design in the past (and did an implementation back in Swift 2 that I never published); it would be as-well-as, rather than instead-of, but it's not actually a bad idea. You start to get into weird typing questions if you aggressively go down this path with the trig functions (by analogy, exp should produce a result type that differs from its argument, with log having the reverse signature, and we need to make the types relate to the angle type when we move to complex operations), but for simpler use cases it can be pretty nice.

@davedelong
Copy link

Random thought...

Having Angle<T: Real> be a struct is good, because it makes it easy to add different representations of the underlying angle. You could easily add a public var turns: T, a public var gons: T, etc.

@jkalias
Copy link

jkalias commented Dec 7, 2020

I'm also in favor of the Angle type. In my code base I constantly have to keep in mind if the angle in a given block of code is in radians or degrees (hint: it's always the Angle type).

I'd be more than happy to help here if needed. Forgive me for asking, but what is the consensus: is the issue still relevant (PR/implementation needed) or is there more discussion required?

jkalias added a commit to jkalias/swift-numerics that referenced this issue Dec 8, 2020
@jkalias
Copy link

jkalias commented May 29, 2022 via email

@mgriebling
Copy link

Gradians are a metric version of radians. Probably not used much but handheld calculators always had a "DRG" key which supported degrees, radians, and gradians. Noticed, that Apple's calculator does not support it.

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

No branches or pull requests

5 participants