From 902f25db3f1326f0d44a61a74adaa8062bf41cec Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Wed, 13 Apr 2022 02:43:17 +0430 Subject: [PATCH] kotlin: Move search context to the end of arguments This, in addition to annotating SearchContext interface as functional, turns it into a more idiomatic Kotlin. --- generate/template/astronomy.kt | 16 ++++++++-------- source/kotlin/README.md | 4 ++-- source/kotlin/doc/-search-context/index.md | 2 +- source/kotlin/doc/index.md | 4 ++-- source/kotlin/doc/search.md | 2 +- .../io/github/cosinekitty/astronomy/astronomy.kt | 16 ++++++++-------- .../io/github/cosinekitty/astronomy/Tests.kt | 7 +------ 7 files changed, 23 insertions(+), 28 deletions(-) diff --git a/generate/template/astronomy.kt b/generate/template/astronomy.kt index 94fd186c..5c06af59 100644 --- a/generate/template/astronomy.kt +++ b/generate/template/astronomy.kt @@ -1940,7 +1940,7 @@ internal fun searchEarthShadow(radiusLimit: Double, direction: Double, t1: Time, override fun eval(time: Time) = direction * (earthShadow(time).r - radiusLimit) } val context = Context(radiusLimit, direction) - return search(context, t1, t2, 1.0) ?: throw InternalError("Failed to find Earth shadow transition.") + return search(t1, t2, 1.0, context) ?: throw InternalError("Failed to find Earth shadow transition.") } @@ -1964,7 +1964,7 @@ internal fun peakEarthShadow(searchCenterTime: Time): ShadowInfo { val window = 0.03 // initial search window, in days, before/after searchCenterTime val t1 = searchCenterTime.addDays(-window) val t2 = searchCenterTime.addDays(+window) - val tx = search(earthShadowSlopeContext, t1, t2, 1.0) ?: + val tx = search(t1, t2, 1.0, earthShadowSlopeContext) ?: throw InternalError("Failed to find Earth peak shadow event.") return earthShadow(tx) } @@ -2190,7 +2190,7 @@ class NodeEventInfo( * A class that implements `SearchContext` can hold state information * needed to evaluate the scalar function `eval`. */ -interface SearchContext { +fun interface SearchContext { /** * Evaluates a scalar function at a given time. * @@ -4457,10 +4457,10 @@ fun jupiterMoons(time: Time) = * window `time1`..`time2`, the function returns `null`. */ fun search( - func: SearchContext, time1: Time, time2: Time, - toleranceSeconds: Double + toleranceSeconds: Double, + func: SearchContext, ): Time? { var t1 = time1 var t2 = time2 @@ -4677,7 +4677,7 @@ fun searchSunLongitude(targetLon: Double, startTime: Time, limitDays: Double): T } val context = Context(targetLon) val time2 = startTime.addDays(limitDays) - return search(context, startTime, time2, 0.01) + return search(startTime, time2, 0.01, context) } /** @@ -4840,7 +4840,7 @@ fun searchMoonPhase(targetLon: Double, startTime: Time, limitDays: Double): Time val dt2 = min(limitDays, estDt + uncertainty) val t1 = startTime.addDays(dt1) val t2 = startTime.addDays(dt2) - return search(moonOffset, t1, t2, 1.0) + return search(t1, t2, 1.0, moonOffset) } /** @@ -5025,7 +5025,7 @@ private fun internalSearchAltitude( if (altBefore <= 0.0 && altAfter > 0.0) { // The body crosses the horizon during the time interval. // Search between evtBefore and evtAfter for the desired event. - val time = search(context, timeBefore, timeAfter, 1.0) + val time = search(timeBefore, timeAfter, 1.0, context) if (time != null) return time } diff --git a/source/kotlin/README.md b/source/kotlin/README.md index 0d5b2f6a..cc2395b8 100644 --- a/source/kotlin/README.md +++ b/source/kotlin/README.md @@ -90,7 +90,7 @@ these are used in function and type names. | [Observer](doc/-observer/index.md) | [jvm]
data class [Observer](doc/-observer/index.md)(latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), height: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
The location of an observer on (or near) the surface of the Earth. | | [Refraction](doc/-refraction/index.md) | [jvm]
enum [Refraction](doc/-refraction/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[Refraction](doc/-refraction/index.md)>
Selects whether to correct for atmospheric refraction, and if so, how. | | [RotationMatrix](doc/-rotation-matrix/index.md) | [jvm]
class [RotationMatrix](doc/-rotation-matrix/index.md)(rot: [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[DoubleArray](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double-array/index.html)>)
A rotation matrix that can be used to transform one coordinate system to another. | -| [SearchContext](doc/-search-context/index.md) | [jvm]
interface [SearchContext](doc/-search-context/index.md)
Represents a function whose ascending root is to be found. | +| [SearchContext](doc/-search-context/index.md) | [jvm]
fun interface [SearchContext](doc/-search-context/index.md)
Represents a function whose ascending root is to be found. | | [SeasonsInfo](doc/-seasons-info/index.md) | [jvm]
class [SeasonsInfo](doc/-seasons-info/index.md)(marchEquinox: [Time](doc/-time/index.md), juneSolstice: [Time](doc/-time/index.md), septemberEquinox: [Time](doc/-time/index.md), decemberSolstice: [Time](doc/-time/index.md))
The dates and times of changes of season for a given calendar year. | | [Spherical](doc/-spherical/index.md) | [jvm]
data class [Spherical](doc/-spherical/index.md)(lat: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), lon: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dist: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
Spherical coordinates: latitude, longitude, distance. | | [StateVector](doc/-state-vector/index.md) | [jvm]
data class [StateVector](doc/-state-vector/index.md)(x: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), y: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), z: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vx: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vy: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vz: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), t: [Time](doc/-time/index.md))
Represents a combined position vector and velocity vector at a given moment in time. | @@ -141,7 +141,7 @@ these are used in function and type names. | [rotationHorEcl](doc/rotation-hor-ecl.md) | [jvm]
fun [rotationHorEcl](doc/rotation-hor-ecl.md)(time: [Time](doc/-time/index.md), observer: [Observer](doc/-observer/index.md)): [RotationMatrix](doc/-rotation-matrix/index.md)
Calculates a rotation matrix from horizontal (HOR) to ecliptic J2000 (ECL). | | [rotationHorEqd](doc/rotation-hor-eqd.md) | [jvm]
fun [rotationHorEqd](doc/rotation-hor-eqd.md)(time: [Time](doc/-time/index.md), observer: [Observer](doc/-observer/index.md)): [RotationMatrix](doc/-rotation-matrix/index.md)
Calculates a rotation matrix from horizontal (HOR) to equatorial of-date (EQD). | | [rotationHorEqj](doc/rotation-hor-eqj.md) | [jvm]
fun [rotationHorEqj](doc/rotation-hor-eqj.md)(time: [Time](doc/-time/index.md), observer: [Observer](doc/-observer/index.md)): [RotationMatrix](doc/-rotation-matrix/index.md)
Calculates a rotation matrix from horizontal (HOR) to J2000 equatorial (EQJ). This is one of the family of functions that returns a rotation matrix for converting from one orientation to another. Source: HOR = horizontal system (x=North, y=West, z=Zenith). Target: EQJ = equatorial system, using equator at the J2000 epoch. | -| [search](doc/search.md) | [jvm]
fun [search](doc/search.md)(func: [SearchContext](doc/-search-context/index.md), time1: [Time](doc/-time/index.md), time2: [Time](doc/-time/index.md), toleranceSeconds: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Time](doc/-time/index.md)?
Searches for a time at which a function's value increases through zero. | +| [search](doc/search.md) | [jvm]
fun [search](doc/search.md)(time1: [Time](doc/-time/index.md), time2: [Time](doc/-time/index.md), toleranceSeconds: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), func: [SearchContext](doc/-search-context/index.md)): [Time](doc/-time/index.md)?
Searches for a time at which a function's value increases through zero. | | [searchAltitude](doc/search-altitude.md) | [jvm]
fun [searchAltitude](doc/search-altitude.md)(body: [Body](doc/-body/index.md), observer: [Observer](doc/-observer/index.md), direction: [Direction](doc/-direction/index.md), startTime: [Time](doc/-time/index.md), limitDays: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), altitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Time](doc/-time/index.md)?
Finds the next time a body reaches a given altitude. | | [searchHourAngle](doc/search-hour-angle.md) | [jvm]
fun [searchHourAngle](doc/search-hour-angle.md)(body: [Body](doc/-body/index.md), observer: [Observer](doc/-observer/index.md), hourAngle: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), startTime: [Time](doc/-time/index.md)): [HourAngleInfo](doc/-hour-angle-info/index.md)
Searches for the time when a celestial body reaches a specified hour angle as seen by an observer on the Earth. | | [searchLunarEclipse](doc/search-lunar-eclipse.md) | [jvm]
fun [searchLunarEclipse](doc/search-lunar-eclipse.md)(startTime: [Time](doc/-time/index.md)): [LunarEclipseInfo](doc/-lunar-eclipse-info/index.md)
Searches for a lunar eclipse. | diff --git a/source/kotlin/doc/-search-context/index.md b/source/kotlin/doc/-search-context/index.md index 6e27195f..ed9c328a 100644 --- a/source/kotlin/doc/-search-context/index.md +++ b/source/kotlin/doc/-search-context/index.md @@ -3,7 +3,7 @@ # SearchContext [jvm]\ -interface [SearchContext](index.md) +fun interface [SearchContext](index.md) Represents a function whose ascending root is to be found. diff --git a/source/kotlin/doc/index.md b/source/kotlin/doc/index.md index ccb61467..9e830e32 100644 --- a/source/kotlin/doc/index.md +++ b/source/kotlin/doc/index.md @@ -35,7 +35,7 @@ | [Observer](-observer/index.md) | [jvm]
data class [Observer](-observer/index.md)(latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), longitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), height: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
The location of an observer on (or near) the surface of the Earth. | | [Refraction](-refraction/index.md) | [jvm]
enum [Refraction](-refraction/index.md) : [Enum](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-enum/index.html)<[Refraction](-refraction/index.md)>
Selects whether to correct for atmospheric refraction, and if so, how. | | [RotationMatrix](-rotation-matrix/index.md) | [jvm]
class [RotationMatrix](-rotation-matrix/index.md)(rot: [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[DoubleArray](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double-array/index.html)>)
A rotation matrix that can be used to transform one coordinate system to another. | -| [SearchContext](-search-context/index.md) | [jvm]
interface [SearchContext](-search-context/index.md)
Represents a function whose ascending root is to be found. | +| [SearchContext](-search-context/index.md) | [jvm]
fun interface [SearchContext](-search-context/index.md)
Represents a function whose ascending root is to be found. | | [SeasonsInfo](-seasons-info/index.md) | [jvm]
class [SeasonsInfo](-seasons-info/index.md)(marchEquinox: [Time](-time/index.md), juneSolstice: [Time](-time/index.md), septemberEquinox: [Time](-time/index.md), decemberSolstice: [Time](-time/index.md))
The dates and times of changes of season for a given calendar year. | | [Spherical](-spherical/index.md) | [jvm]
data class [Spherical](-spherical/index.md)(lat: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), lon: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dist: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html))
Spherical coordinates: latitude, longitude, distance. | | [StateVector](-state-vector/index.md) | [jvm]
data class [StateVector](-state-vector/index.md)(x: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), y: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), z: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vx: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vy: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), vz: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), t: [Time](-time/index.md))
Represents a combined position vector and velocity vector at a given moment in time. | @@ -86,7 +86,7 @@ | [rotationHorEcl](rotation-hor-ecl.md) | [jvm]
fun [rotationHorEcl](rotation-hor-ecl.md)(time: [Time](-time/index.md), observer: [Observer](-observer/index.md)): [RotationMatrix](-rotation-matrix/index.md)
Calculates a rotation matrix from horizontal (HOR) to ecliptic J2000 (ECL). | | [rotationHorEqd](rotation-hor-eqd.md) | [jvm]
fun [rotationHorEqd](rotation-hor-eqd.md)(time: [Time](-time/index.md), observer: [Observer](-observer/index.md)): [RotationMatrix](-rotation-matrix/index.md)
Calculates a rotation matrix from horizontal (HOR) to equatorial of-date (EQD). | | [rotationHorEqj](rotation-hor-eqj.md) | [jvm]
fun [rotationHorEqj](rotation-hor-eqj.md)(time: [Time](-time/index.md), observer: [Observer](-observer/index.md)): [RotationMatrix](-rotation-matrix/index.md)
Calculates a rotation matrix from horizontal (HOR) to J2000 equatorial (EQJ). This is one of the family of functions that returns a rotation matrix for converting from one orientation to another. Source: HOR = horizontal system (x=North, y=West, z=Zenith). Target: EQJ = equatorial system, using equator at the J2000 epoch. | -| [search](search.md) | [jvm]
fun [search](search.md)(func: [SearchContext](-search-context/index.md), time1: [Time](-time/index.md), time2: [Time](-time/index.md), toleranceSeconds: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Time](-time/index.md)?
Searches for a time at which a function's value increases through zero. | +| [search](search.md) | [jvm]
fun [search](search.md)(time1: [Time](-time/index.md), time2: [Time](-time/index.md), toleranceSeconds: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), func: [SearchContext](-search-context/index.md)): [Time](-time/index.md)?
Searches for a time at which a function's value increases through zero. | | [searchAltitude](search-altitude.md) | [jvm]
fun [searchAltitude](search-altitude.md)(body: [Body](-body/index.md), observer: [Observer](-observer/index.md), direction: [Direction](-direction/index.md), startTime: [Time](-time/index.md), limitDays: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), altitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Time](-time/index.md)?
Finds the next time a body reaches a given altitude. | | [searchHourAngle](search-hour-angle.md) | [jvm]
fun [searchHourAngle](search-hour-angle.md)(body: [Body](-body/index.md), observer: [Observer](-observer/index.md), hourAngle: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), startTime: [Time](-time/index.md)): [HourAngleInfo](-hour-angle-info/index.md)
Searches for the time when a celestial body reaches a specified hour angle as seen by an observer on the Earth. | | [searchLunarEclipse](search-lunar-eclipse.md) | [jvm]
fun [searchLunarEclipse](search-lunar-eclipse.md)(startTime: [Time](-time/index.md)): [LunarEclipseInfo](-lunar-eclipse-info/index.md)
Searches for a lunar eclipse. | diff --git a/source/kotlin/doc/search.md b/source/kotlin/doc/search.md index 03d7bfd0..c418eaea 100644 --- a/source/kotlin/doc/search.md +++ b/source/kotlin/doc/search.md @@ -3,7 +3,7 @@ # search [jvm]\ -fun [search](search.md)(func: [SearchContext](-search-context/index.md), time1: [Time](-time/index.md), time2: [Time](-time/index.md), toleranceSeconds: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Time](-time/index.md)? +fun [search](search.md)(time1: [Time](-time/index.md), time2: [Time](-time/index.md), toleranceSeconds: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), func: [SearchContext](-search-context/index.md)): [Time](-time/index.md)? Searches for a time at which a function's value increases through zero. diff --git a/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt b/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt index f5215a7b..dcce4e37 100644 --- a/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt +++ b/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt @@ -1940,7 +1940,7 @@ internal fun searchEarthShadow(radiusLimit: Double, direction: Double, t1: Time, override fun eval(time: Time) = direction * (earthShadow(time).r - radiusLimit) } val context = Context(radiusLimit, direction) - return search(context, t1, t2, 1.0) ?: throw InternalError("Failed to find Earth shadow transition.") + return search(t1, t2, 1.0, context) ?: throw InternalError("Failed to find Earth shadow transition.") } @@ -1964,7 +1964,7 @@ internal fun peakEarthShadow(searchCenterTime: Time): ShadowInfo { val window = 0.03 // initial search window, in days, before/after searchCenterTime val t1 = searchCenterTime.addDays(-window) val t2 = searchCenterTime.addDays(+window) - val tx = search(earthShadowSlopeContext, t1, t2, 1.0) ?: + val tx = search(t1, t2, 1.0, earthShadowSlopeContext) ?: throw InternalError("Failed to find Earth peak shadow event.") return earthShadow(tx) } @@ -2190,7 +2190,7 @@ class NodeEventInfo( * A class that implements `SearchContext` can hold state information * needed to evaluate the scalar function `eval`. */ -interface SearchContext { +fun interface SearchContext { /** * Evaluates a scalar function at a given time. * @@ -4457,10 +4457,10 @@ fun jupiterMoons(time: Time) = * window `time1`..`time2`, the function returns `null`. */ fun search( - func: SearchContext, time1: Time, time2: Time, - toleranceSeconds: Double + toleranceSeconds: Double, + func: SearchContext, ): Time? { var t1 = time1 var t2 = time2 @@ -4677,7 +4677,7 @@ fun searchSunLongitude(targetLon: Double, startTime: Time, limitDays: Double): T } val context = Context(targetLon) val time2 = startTime.addDays(limitDays) - return search(context, startTime, time2, 0.01) + return search(startTime, time2, 0.01, context) } /** @@ -4840,7 +4840,7 @@ fun searchMoonPhase(targetLon: Double, startTime: Time, limitDays: Double): Time val dt2 = min(limitDays, estDt + uncertainty) val t1 = startTime.addDays(dt1) val t2 = startTime.addDays(dt2) - return search(moonOffset, t1, t2, 1.0) + return search(t1, t2, 1.0, moonOffset) } /** @@ -5025,7 +5025,7 @@ private fun internalSearchAltitude( if (altBefore <= 0.0 && altAfter > 0.0) { // The body crosses the horizon during the time interval. // Search between evtBefore and evtAfter for the desired event. - val time = search(context, timeBefore, timeAfter, 1.0) + val time = search(timeBefore, timeAfter, 1.0, context) if (time != null) return time } diff --git a/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt b/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt index 29ec3a3a..5484382f 100644 --- a/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt +++ b/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt @@ -732,16 +732,11 @@ class Tests { @Test fun `Basic search`() { - class CosineIdentityFunc : SearchContext { - override fun eval(time: Time) = time.ut - cos(time.ut) - } - val toleranceDays = 1.0e-9 val toleranceSeconds = toleranceDays / 86400.0 - val func = CosineIdentityFunc() val time1 = Time(0.0) val time2 = Time(1.0) - val tsolve = search(func, time1, time2, toleranceSeconds) + val tsolve = search(time1, time2, toleranceSeconds) { time -> time.ut - cos(time.ut) } if (tsolve == null) fail("Basic search failed")