mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 00:11:04 +00:00 
			
		
		
		
	Upgrade blevesearch dependency to v2.0.1 (#14346)
* Upgrade blevesearch dependency to v2.0.1 * Update rupture to v1.0.0 * Fix test
This commit is contained in:
		
					parent
					
						
							
								3aa53dc6bc
							
						
					
				
			
			
				commit
				
					
						f5abe2f563
					
				
			
		
					 459 changed files with 7518 additions and 4211 deletions
				
			
		
							
								
								
									
										9
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
# geo support in bleve
 | 
			
		||||
 | 
			
		||||
First, all of this geo code is a Go adaptation of the [Lucene 5.3.2 sandbox geo support](https://lucene.apache.org/core/5_3_2/sandbox/org/apache/lucene/util/package-summary.html).
 | 
			
		||||
 | 
			
		||||
## Notes
 | 
			
		||||
 | 
			
		||||
- All of the APIs will use float64 for lon/lat values.
 | 
			
		||||
- When describing a point in function arguments or return values, we always use the order lon, lat.
 | 
			
		||||
- High level APIs will use TopLeft and BottomRight to describe bounding boxes.  This may not map cleanly to min/max lon/lat when crossing the dateline.  The lower level APIs will use min/max lon/lat and require the higher-level code to split boxes accordingly.
 | 
			
		||||
							
								
								
									
										210
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/geo.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/geo.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,210 @@
 | 
			
		|||
//  Copyright (c) 2017 Couchbase, Inc.
 | 
			
		||||
//
 | 
			
		||||
// 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 geo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
 | 
			
		||||
	"github.com/blevesearch/bleve/v2/numeric"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GeoBits is the number of bits used for a single geo point
 | 
			
		||||
// Currently this is 32bits for lon and 32bits for lat
 | 
			
		||||
var GeoBits uint = 32
 | 
			
		||||
 | 
			
		||||
var minLon = -180.0
 | 
			
		||||
var minLat = -90.0
 | 
			
		||||
var maxLon = 180.0
 | 
			
		||||
var maxLat = 90.0
 | 
			
		||||
var minLonRad = minLon * degreesToRadian
 | 
			
		||||
var minLatRad = minLat * degreesToRadian
 | 
			
		||||
var maxLonRad = maxLon * degreesToRadian
 | 
			
		||||
var maxLatRad = maxLat * degreesToRadian
 | 
			
		||||
var geoTolerance = 1e-6
 | 
			
		||||
var lonScale = float64((uint64(0x1)<<GeoBits)-1) / 360.0
 | 
			
		||||
var latScale = float64((uint64(0x1)<<GeoBits)-1) / 180.0
 | 
			
		||||
 | 
			
		||||
var geoHashMaxLength = 12
 | 
			
		||||
 | 
			
		||||
// Point represents a geo point.
 | 
			
		||||
type Point struct {
 | 
			
		||||
	Lon float64 `json:"lon"`
 | 
			
		||||
	Lat float64 `json:"lat"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MortonHash computes the morton hash value for the provided geo point
 | 
			
		||||
// This point is ordered as lon, lat.
 | 
			
		||||
func MortonHash(lon, lat float64) uint64 {
 | 
			
		||||
	return numeric.Interleave(scaleLon(lon), scaleLat(lat))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scaleLon(lon float64) uint64 {
 | 
			
		||||
	rv := uint64((lon - minLon) * lonScale)
 | 
			
		||||
	return rv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scaleLat(lat float64) uint64 {
 | 
			
		||||
	rv := uint64((lat - minLat) * latScale)
 | 
			
		||||
	return rv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MortonUnhashLon extracts the longitude value from the provided morton hash.
 | 
			
		||||
func MortonUnhashLon(hash uint64) float64 {
 | 
			
		||||
	return unscaleLon(numeric.Deinterleave(hash))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MortonUnhashLat extracts the latitude value from the provided morton hash.
 | 
			
		||||
func MortonUnhashLat(hash uint64) float64 {
 | 
			
		||||
	return unscaleLat(numeric.Deinterleave(hash >> 1))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func unscaleLon(lon uint64) float64 {
 | 
			
		||||
	return (float64(lon) / lonScale) + minLon
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func unscaleLat(lat uint64) float64 {
 | 
			
		||||
	return (float64(lat) / latScale) + minLat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// compareGeo will compare two float values and see if they are the same
 | 
			
		||||
// taking into consideration a known geo tolerance.
 | 
			
		||||
func compareGeo(a, b float64) float64 {
 | 
			
		||||
	compare := a - b
 | 
			
		||||
	if math.Abs(compare) <= geoTolerance {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return compare
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RectIntersects checks whether rectangles a and b intersect
 | 
			
		||||
func RectIntersects(aMinX, aMinY, aMaxX, aMaxY, bMinX, bMinY, bMaxX, bMaxY float64) bool {
 | 
			
		||||
	return !(aMaxX < bMinX || aMinX > bMaxX || aMaxY < bMinY || aMinY > bMaxY)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RectWithin checks whether box a is within box b
 | 
			
		||||
func RectWithin(aMinX, aMinY, aMaxX, aMaxY, bMinX, bMinY, bMaxX, bMaxY float64) bool {
 | 
			
		||||
	rv := !(aMinX < bMinX || aMinY < bMinY || aMaxX > bMaxX || aMaxY > bMaxY)
 | 
			
		||||
	return rv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BoundingBoxContains checks whether the lon/lat point is within the box
 | 
			
		||||
func BoundingBoxContains(lon, lat, minLon, minLat, maxLon, maxLat float64) bool {
 | 
			
		||||
	return compareGeo(lon, minLon) >= 0 && compareGeo(lon, maxLon) <= 0 &&
 | 
			
		||||
		compareGeo(lat, minLat) >= 0 && compareGeo(lat, maxLat) <= 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const degreesToRadian = math.Pi / 180
 | 
			
		||||
const radiansToDegrees = 180 / math.Pi
 | 
			
		||||
 | 
			
		||||
// DegreesToRadians converts an angle in degrees to radians
 | 
			
		||||
func DegreesToRadians(d float64) float64 {
 | 
			
		||||
	return d * degreesToRadian
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RadiansToDegrees converts an angle in radians to degress
 | 
			
		||||
func RadiansToDegrees(r float64) float64 {
 | 
			
		||||
	return r * radiansToDegrees
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var earthMeanRadiusMeters = 6371008.7714
 | 
			
		||||
 | 
			
		||||
func RectFromPointDistance(lon, lat, dist float64) (float64, float64, float64, float64, error) {
 | 
			
		||||
	err := checkLongitude(lon)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	err = checkLatitude(lat)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	radLon := DegreesToRadians(lon)
 | 
			
		||||
	radLat := DegreesToRadians(lat)
 | 
			
		||||
	radDistance := (dist + 7e-2) / earthMeanRadiusMeters
 | 
			
		||||
 | 
			
		||||
	minLatL := radLat - radDistance
 | 
			
		||||
	maxLatL := radLat + radDistance
 | 
			
		||||
 | 
			
		||||
	var minLonL, maxLonL float64
 | 
			
		||||
	if minLatL > minLatRad && maxLatL < maxLatRad {
 | 
			
		||||
		deltaLon := asin(sin(radDistance) / cos(radLat))
 | 
			
		||||
		minLonL = radLon - deltaLon
 | 
			
		||||
		if minLonL < minLonRad {
 | 
			
		||||
			minLonL += 2 * math.Pi
 | 
			
		||||
		}
 | 
			
		||||
		maxLonL = radLon + deltaLon
 | 
			
		||||
		if maxLonL > maxLonRad {
 | 
			
		||||
			maxLonL -= 2 * math.Pi
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// pole is inside distance
 | 
			
		||||
		minLatL = math.Max(minLatL, minLatRad)
 | 
			
		||||
		maxLatL = math.Min(maxLatL, maxLatRad)
 | 
			
		||||
		minLonL = minLonRad
 | 
			
		||||
		maxLonL = maxLonRad
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return RadiansToDegrees(minLonL),
 | 
			
		||||
		RadiansToDegrees(maxLatL),
 | 
			
		||||
		RadiansToDegrees(maxLonL),
 | 
			
		||||
		RadiansToDegrees(minLatL),
 | 
			
		||||
		nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkLatitude(latitude float64) error {
 | 
			
		||||
	if math.IsNaN(latitude) || latitude < minLat || latitude > maxLat {
 | 
			
		||||
		return fmt.Errorf("invalid latitude %f; must be between %f and %f", latitude, minLat, maxLat)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkLongitude(longitude float64) error {
 | 
			
		||||
	if math.IsNaN(longitude) || longitude < minLon || longitude > maxLon {
 | 
			
		||||
		return fmt.Errorf("invalid longitude %f; must be between %f and %f", longitude, minLon, maxLon)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BoundingRectangleForPolygon(polygon []Point) (
 | 
			
		||||
	float64, float64, float64, float64, error) {
 | 
			
		||||
	err := checkLongitude(polygon[0].Lon)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	err = checkLatitude(polygon[0].Lat)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, 0, 0, err
 | 
			
		||||
	}
 | 
			
		||||
	maxY, minY := polygon[0].Lat, polygon[0].Lat
 | 
			
		||||
	maxX, minX := polygon[0].Lon, polygon[0].Lon
 | 
			
		||||
	for i := 1; i < len(polygon); i++ {
 | 
			
		||||
		err := checkLongitude(polygon[i].Lon)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, 0, 0, 0, err
 | 
			
		||||
		}
 | 
			
		||||
		err = checkLatitude(polygon[i].Lat)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, 0, 0, 0, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		maxY = math.Max(maxY, polygon[i].Lat)
 | 
			
		||||
		minY = math.Min(minY, polygon[i].Lat)
 | 
			
		||||
 | 
			
		||||
		maxX = math.Max(maxX, polygon[i].Lon)
 | 
			
		||||
		minX = math.Min(minX, polygon[i].Lon)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return minX, maxY, maxX, minY, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/geo_dist.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/geo_dist.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
//  Copyright (c) 2017 Couchbase, Inc.
 | 
			
		||||
//
 | 
			
		||||
// 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 geo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type distanceUnit struct {
 | 
			
		||||
	conv     float64
 | 
			
		||||
	suffixes []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var inch = distanceUnit{0.0254, []string{"in", "inch"}}
 | 
			
		||||
var yard = distanceUnit{0.9144, []string{"yd", "yards"}}
 | 
			
		||||
var feet = distanceUnit{0.3048, []string{"ft", "feet"}}
 | 
			
		||||
var kilom = distanceUnit{1000, []string{"km", "kilometers"}}
 | 
			
		||||
var nauticalm = distanceUnit{1852.0, []string{"nm", "nauticalmiles"}}
 | 
			
		||||
var millim = distanceUnit{0.001, []string{"mm", "millimeters"}}
 | 
			
		||||
var centim = distanceUnit{0.01, []string{"cm", "centimeters"}}
 | 
			
		||||
var miles = distanceUnit{1609.344, []string{"mi", "miles"}}
 | 
			
		||||
var meters = distanceUnit{1, []string{"m", "meters"}}
 | 
			
		||||
 | 
			
		||||
var distanceUnits = []*distanceUnit{
 | 
			
		||||
	&inch, &yard, &feet, &kilom, &nauticalm, &millim, ¢im, &miles, &meters,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDistance attempts to parse a distance string and return distance in
 | 
			
		||||
// meters.  Example formats supported:
 | 
			
		||||
// "5in" "5inch" "7yd" "7yards" "9ft" "9feet" "11km" "11kilometers"
 | 
			
		||||
// "3nm" "3nauticalmiles" "13mm" "13millimeters" "15cm" "15centimeters"
 | 
			
		||||
// "17mi" "17miles" "19m" "19meters"
 | 
			
		||||
// If the unit cannot be determined, the entire string is parsed and the
 | 
			
		||||
// unit of meters is assumed.
 | 
			
		||||
// If the number portion cannot be parsed, 0 and the parse error are returned.
 | 
			
		||||
func ParseDistance(d string) (float64, error) {
 | 
			
		||||
	for _, unit := range distanceUnits {
 | 
			
		||||
		for _, unitSuffix := range unit.suffixes {
 | 
			
		||||
			if strings.HasSuffix(d, unitSuffix) {
 | 
			
		||||
				parsedNum, err := strconv.ParseFloat(d[0:len(d)-len(unitSuffix)], 64)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return 0, err
 | 
			
		||||
				}
 | 
			
		||||
				return parsedNum * unit.conv, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// no unit matched, try assuming meters?
 | 
			
		||||
	parsedNum, err := strconv.ParseFloat(d, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return parsedNum, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDistanceUnit attempts to parse a distance unit and return the
 | 
			
		||||
// multiplier for converting this to meters.  If the unit cannot be parsed
 | 
			
		||||
// then 0 and the error message is returned.
 | 
			
		||||
func ParseDistanceUnit(u string) (float64, error) {
 | 
			
		||||
	for _, unit := range distanceUnits {
 | 
			
		||||
		for _, unitSuffix := range unit.suffixes {
 | 
			
		||||
			if u == unitSuffix {
 | 
			
		||||
				return unit.conv, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, fmt.Errorf("unknown distance unit: %s", u)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Haversin computes the distance between two points.
 | 
			
		||||
// This implemenation uses the sloppy math implemenations which trade off
 | 
			
		||||
// accuracy for performance.  The distance returned is in kilometers.
 | 
			
		||||
func Haversin(lon1, lat1, lon2, lat2 float64) float64 {
 | 
			
		||||
	x1 := lat1 * degreesToRadian
 | 
			
		||||
	x2 := lat2 * degreesToRadian
 | 
			
		||||
	h1 := 1 - cos(x1-x2)
 | 
			
		||||
	h2 := 1 - cos((lon1-lon2)*degreesToRadian)
 | 
			
		||||
	h := (h1 + cos(x1)*cos(x2)*h2) / 2
 | 
			
		||||
	avgLat := (x1 + x2) / 2
 | 
			
		||||
	diameter := earthDiameter(avgLat)
 | 
			
		||||
 | 
			
		||||
	return diameter * asin(math.Min(1, math.Sqrt(h)))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										111
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/geohash.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/geohash.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,111 @@
 | 
			
		|||
//  Copyright (c) 2019 Couchbase, Inc.
 | 
			
		||||
//
 | 
			
		||||
// 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.
 | 
			
		||||
// This implementation is inspired from the geohash-js
 | 
			
		||||
// ref: https://github.com/davetroy/geohash-js
 | 
			
		||||
 | 
			
		||||
package geo
 | 
			
		||||
 | 
			
		||||
// encoding encapsulates an encoding defined by a given base32 alphabet.
 | 
			
		||||
type encoding struct {
 | 
			
		||||
	enc string
 | 
			
		||||
	dec [256]byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newEncoding constructs a new encoding defined by the given alphabet,
 | 
			
		||||
// which must be a 32-byte string.
 | 
			
		||||
func newEncoding(encoder string) *encoding {
 | 
			
		||||
	e := new(encoding)
 | 
			
		||||
	e.enc = encoder
 | 
			
		||||
	for i := 0; i < len(e.dec); i++ {
 | 
			
		||||
		e.dec[i] = 0xff
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < len(encoder); i++ {
 | 
			
		||||
		e.dec[encoder[i]] = byte(i)
 | 
			
		||||
	}
 | 
			
		||||
	return e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// base32encoding with the Geohash alphabet.
 | 
			
		||||
var base32encoding = newEncoding("0123456789bcdefghjkmnpqrstuvwxyz")
 | 
			
		||||
 | 
			
		||||
var masks = []uint64{16, 8, 4, 2, 1}
 | 
			
		||||
 | 
			
		||||
// DecodeGeoHash decodes the string geohash faster with
 | 
			
		||||
// higher precision. This api is in experimental phase.
 | 
			
		||||
func DecodeGeoHash(geoHash string) (float64, float64) {
 | 
			
		||||
	even := true
 | 
			
		||||
	lat := []float64{-90.0, 90.0}
 | 
			
		||||
	lon := []float64{-180.0, 180.0}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < len(geoHash); i++ {
 | 
			
		||||
		cd := uint64(base32encoding.dec[geoHash[i]])
 | 
			
		||||
		for j := 0; j < 5; j++ {
 | 
			
		||||
			if even {
 | 
			
		||||
				if cd&masks[j] > 0 {
 | 
			
		||||
					lon[0] = (lon[0] + lon[1]) / 2
 | 
			
		||||
				} else {
 | 
			
		||||
					lon[1] = (lon[0] + lon[1]) / 2
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if cd&masks[j] > 0 {
 | 
			
		||||
					lat[0] = (lat[0] + lat[1]) / 2
 | 
			
		||||
				} else {
 | 
			
		||||
					lat[1] = (lat[0] + lat[1]) / 2
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			even = !even
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (lat[0] + lat[1]) / 2, (lon[0] + lon[1]) / 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func EncodeGeoHash(lat, lon float64) string {
 | 
			
		||||
	even := true
 | 
			
		||||
	lats := []float64{-90.0, 90.0}
 | 
			
		||||
	lons := []float64{-180.0, 180.0}
 | 
			
		||||
	precision := 12
 | 
			
		||||
	var ch, bit uint64
 | 
			
		||||
	var geoHash string
 | 
			
		||||
 | 
			
		||||
	for len(geoHash) < precision {
 | 
			
		||||
		if even {
 | 
			
		||||
			mid := (lons[0] + lons[1]) / 2
 | 
			
		||||
			if lon > mid {
 | 
			
		||||
				ch |= masks[bit]
 | 
			
		||||
				lons[0] = mid
 | 
			
		||||
			} else {
 | 
			
		||||
				lons[1] = mid
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			mid := (lats[0] + lats[1]) / 2
 | 
			
		||||
			if lat > mid {
 | 
			
		||||
				ch |= masks[bit]
 | 
			
		||||
				lats[0] = mid
 | 
			
		||||
			} else {
 | 
			
		||||
				lats[1] = mid
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		even = !even
 | 
			
		||||
		if bit < 4 {
 | 
			
		||||
			bit++
 | 
			
		||||
		} else {
 | 
			
		||||
			geoHash += string(base32encoding.enc[ch])
 | 
			
		||||
			ch = 0
 | 
			
		||||
			bit = 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return geoHash
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										181
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/parse.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/parse.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,181 @@
 | 
			
		|||
//  Copyright (c) 2017 Couchbase, Inc.
 | 
			
		||||
//
 | 
			
		||||
// 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 geo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ExtractGeoPoint takes an arbitrary interface{} and tries it's best to
 | 
			
		||||
// interpret it is as geo point.  Supported formats:
 | 
			
		||||
// Container:
 | 
			
		||||
// slice length 2 (GeoJSON)
 | 
			
		||||
//  first element lon, second element lat
 | 
			
		||||
// string (coordinates separated by comma, or a geohash)
 | 
			
		||||
//  first element lat, second element lon
 | 
			
		||||
// map[string]interface{}
 | 
			
		||||
//  exact keys lat and lon or lng
 | 
			
		||||
// struct
 | 
			
		||||
//  w/exported fields case-insensitive match on lat and lon or lng
 | 
			
		||||
// struct
 | 
			
		||||
//  satisfying Later and Loner or Lnger interfaces
 | 
			
		||||
//
 | 
			
		||||
// in all cases values must be some sort of numeric-like thing: int/uint/float
 | 
			
		||||
func ExtractGeoPoint(thing interface{}) (lon, lat float64, success bool) {
 | 
			
		||||
	var foundLon, foundLat bool
 | 
			
		||||
 | 
			
		||||
	thingVal := reflect.ValueOf(thing)
 | 
			
		||||
	if !thingVal.IsValid() {
 | 
			
		||||
		return lon, lat, false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	thingTyp := thingVal.Type()
 | 
			
		||||
 | 
			
		||||
	// is it a slice
 | 
			
		||||
	if thingVal.Kind() == reflect.Slice {
 | 
			
		||||
		// must be length 2
 | 
			
		||||
		if thingVal.Len() == 2 {
 | 
			
		||||
			first := thingVal.Index(0)
 | 
			
		||||
			if first.CanInterface() {
 | 
			
		||||
				firstVal := first.Interface()
 | 
			
		||||
				lon, foundLon = extractNumericVal(firstVal)
 | 
			
		||||
			}
 | 
			
		||||
			second := thingVal.Index(1)
 | 
			
		||||
			if second.CanInterface() {
 | 
			
		||||
				secondVal := second.Interface()
 | 
			
		||||
				lat, foundLat = extractNumericVal(secondVal)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// is it a string
 | 
			
		||||
	if thingVal.Kind() == reflect.String {
 | 
			
		||||
		geoStr := thingVal.Interface().(string)
 | 
			
		||||
		if strings.Contains(geoStr, ",") {
 | 
			
		||||
			// geo point with coordinates split by comma
 | 
			
		||||
			points := strings.Split(geoStr, ",")
 | 
			
		||||
			for i, point := range points {
 | 
			
		||||
				// trim any leading or trailing white spaces
 | 
			
		||||
				points[i] = strings.TrimSpace(point)
 | 
			
		||||
			}
 | 
			
		||||
			if len(points) == 2 {
 | 
			
		||||
				var err error
 | 
			
		||||
				lat, err = strconv.ParseFloat(points[0], 64)
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					foundLat = true
 | 
			
		||||
				}
 | 
			
		||||
				lon, err = strconv.ParseFloat(points[1], 64)
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					foundLon = true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// geohash
 | 
			
		||||
			if len(geoStr) <= geoHashMaxLength {
 | 
			
		||||
				lat, lon = DecodeGeoHash(geoStr)
 | 
			
		||||
				foundLat = true
 | 
			
		||||
				foundLon = true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// is it a map
 | 
			
		||||
	if l, ok := thing.(map[string]interface{}); ok {
 | 
			
		||||
		if lval, ok := l["lon"]; ok {
 | 
			
		||||
			lon, foundLon = extractNumericVal(lval)
 | 
			
		||||
		} else if lval, ok := l["lng"]; ok {
 | 
			
		||||
			lon, foundLon = extractNumericVal(lval)
 | 
			
		||||
		}
 | 
			
		||||
		if lval, ok := l["lat"]; ok {
 | 
			
		||||
			lat, foundLat = extractNumericVal(lval)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// now try reflection on struct fields
 | 
			
		||||
	if thingVal.Kind() == reflect.Struct {
 | 
			
		||||
		for i := 0; i < thingVal.NumField(); i++ {
 | 
			
		||||
			fieldName := thingTyp.Field(i).Name
 | 
			
		||||
			if strings.HasPrefix(strings.ToLower(fieldName), "lon") {
 | 
			
		||||
				if thingVal.Field(i).CanInterface() {
 | 
			
		||||
					fieldVal := thingVal.Field(i).Interface()
 | 
			
		||||
					lon, foundLon = extractNumericVal(fieldVal)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if strings.HasPrefix(strings.ToLower(fieldName), "lng") {
 | 
			
		||||
				if thingVal.Field(i).CanInterface() {
 | 
			
		||||
					fieldVal := thingVal.Field(i).Interface()
 | 
			
		||||
					lon, foundLon = extractNumericVal(fieldVal)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if strings.HasPrefix(strings.ToLower(fieldName), "lat") {
 | 
			
		||||
				if thingVal.Field(i).CanInterface() {
 | 
			
		||||
					fieldVal := thingVal.Field(i).Interface()
 | 
			
		||||
					lat, foundLat = extractNumericVal(fieldVal)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// last hope, some interfaces
 | 
			
		||||
	// lon
 | 
			
		||||
	if l, ok := thing.(loner); ok {
 | 
			
		||||
		lon = l.Lon()
 | 
			
		||||
		foundLon = true
 | 
			
		||||
	} else if l, ok := thing.(lnger); ok {
 | 
			
		||||
		lon = l.Lng()
 | 
			
		||||
		foundLon = true
 | 
			
		||||
	}
 | 
			
		||||
	// lat
 | 
			
		||||
	if l, ok := thing.(later); ok {
 | 
			
		||||
		lat = l.Lat()
 | 
			
		||||
		foundLat = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lon, lat, foundLon && foundLat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// extract numeric value (if possible) and returns a float64
 | 
			
		||||
func extractNumericVal(v interface{}) (float64, bool) {
 | 
			
		||||
	val := reflect.ValueOf(v)
 | 
			
		||||
	if !val.IsValid() {
 | 
			
		||||
		return 0, false
 | 
			
		||||
	}
 | 
			
		||||
	typ := val.Type()
 | 
			
		||||
	switch typ.Kind() {
 | 
			
		||||
	case reflect.Float32, reflect.Float64:
 | 
			
		||||
		return val.Float(), true
 | 
			
		||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
			
		||||
		return float64(val.Int()), true
 | 
			
		||||
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		return float64(val.Uint()), true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// various support interfaces which can be used to find lat/lon
 | 
			
		||||
type loner interface {
 | 
			
		||||
	Lon() float64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type later interface {
 | 
			
		||||
	Lat() float64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type lnger interface {
 | 
			
		||||
	Lng() float64
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										212
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/sloppy.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								vendor/github.com/blevesearch/bleve/v2/geo/sloppy.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,212 @@
 | 
			
		|||
//  Copyright (c) 2017 Couchbase, Inc.
 | 
			
		||||
//
 | 
			
		||||
// 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 geo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var earthDiameterPerLatitude []float64
 | 
			
		||||
var sinTab []float64
 | 
			
		||||
var cosTab []float64
 | 
			
		||||
var asinTab []float64
 | 
			
		||||
var asinDer1DivF1Tab []float64
 | 
			
		||||
var asinDer2DivF2Tab []float64
 | 
			
		||||
var asinDer3DivF3Tab []float64
 | 
			
		||||
var asinDer4DivF4Tab []float64
 | 
			
		||||
 | 
			
		||||
const radiusTabsSize = (1 << 10) + 1
 | 
			
		||||
const radiusDelta = (math.Pi / 2) / (radiusTabsSize - 1)
 | 
			
		||||
const radiusIndexer = 1 / radiusDelta
 | 
			
		||||
const sinCosTabsSize = (1 << 11) + 1
 | 
			
		||||
const asinTabsSize = (1 << 13) + 1
 | 
			
		||||
const oneDivF2 = 1 / 2.0
 | 
			
		||||
const oneDivF3 = 1 / 6.0
 | 
			
		||||
const oneDivF4 = 1 / 24.0
 | 
			
		||||
 | 
			
		||||
// 1.57079632673412561417e+00 first 33 bits of pi/2
 | 
			
		||||
var pio2Hi = math.Float64frombits(0x3FF921FB54400000)
 | 
			
		||||
 | 
			
		||||
// 6.07710050650619224932e-11 pi/2 - PIO2_HI
 | 
			
		||||
var pio2Lo = math.Float64frombits(0x3DD0B4611A626331)
 | 
			
		||||
 | 
			
		||||
var asinPio2Hi = math.Float64frombits(0x3FF921FB54442D18) // 1.57079632679489655800e+00
 | 
			
		||||
var asinPio2Lo = math.Float64frombits(0x3C91A62633145C07) // 6.12323399573676603587e-17
 | 
			
		||||
var asinPs0 = math.Float64frombits(0x3fc5555555555555)    //  1.66666666666666657415e-01
 | 
			
		||||
var asinPs1 = math.Float64frombits(0xbfd4d61203eb6f7d)    // -3.25565818622400915405e-01
 | 
			
		||||
var asinPs2 = math.Float64frombits(0x3fc9c1550e884455)    //  2.01212532134862925881e-01
 | 
			
		||||
var asinPs3 = math.Float64frombits(0xbfa48228b5688f3b)    // -4.00555345006794114027e-02
 | 
			
		||||
var asinPs4 = math.Float64frombits(0x3f49efe07501b288)    //  7.91534994289814532176e-04
 | 
			
		||||
var asinPs5 = math.Float64frombits(0x3f023de10dfdf709)    //  3.47933107596021167570e-05
 | 
			
		||||
var asinQs1 = math.Float64frombits(0xc0033a271c8a2d4b)    // -2.40339491173441421878e+00
 | 
			
		||||
var asinQs2 = math.Float64frombits(0x40002ae59c598ac8)    //  2.02094576023350569471e+00
 | 
			
		||||
var asinQs3 = math.Float64frombits(0xbfe6066c1b8d0159)    // -6.88283971605453293030e-01
 | 
			
		||||
var asinQs4 = math.Float64frombits(0x3fb3b8c5b12e9282)    //  7.70381505559019352791e-02
 | 
			
		||||
 | 
			
		||||
var twoPiHi = 4 * pio2Hi
 | 
			
		||||
var twoPiLo = 4 * pio2Lo
 | 
			
		||||
var sinCosDeltaHi = twoPiHi/sinCosTabsSize - 1
 | 
			
		||||
var sinCosDeltaLo = twoPiLo/sinCosTabsSize - 1
 | 
			
		||||
var sinCosIndexer = 1 / (sinCosDeltaHi + sinCosDeltaLo)
 | 
			
		||||
var sinCosMaxValueForIntModulo = ((math.MaxInt64 >> 9) / sinCosIndexer) * 0.99
 | 
			
		||||
var asinMaxValueForTabs = math.Sin(73.0 * degreesToRadian)
 | 
			
		||||
 | 
			
		||||
var asinDelta = asinMaxValueForTabs / (asinTabsSize - 1)
 | 
			
		||||
var asinIndexer = 1 / asinDelta
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	// initializes the tables used for the sloppy math functions
 | 
			
		||||
 | 
			
		||||
	// sin and cos
 | 
			
		||||
	sinTab = make([]float64, sinCosTabsSize)
 | 
			
		||||
	cosTab = make([]float64, sinCosTabsSize)
 | 
			
		||||
	sinCosPiIndex := (sinCosTabsSize - 1) / 2
 | 
			
		||||
	sinCosPiMul2Index := 2 * sinCosPiIndex
 | 
			
		||||
	sinCosPiMul05Index := sinCosPiIndex / 2
 | 
			
		||||
	sinCosPiMul15Index := 3 * sinCosPiIndex / 2
 | 
			
		||||
	for i := 0; i < sinCosTabsSize; i++ {
 | 
			
		||||
		// angle: in [0,2*PI].
 | 
			
		||||
		angle := float64(i)*sinCosDeltaHi + float64(i)*sinCosDeltaLo
 | 
			
		||||
		sinAngle := math.Sin(angle)
 | 
			
		||||
		cosAngle := math.Cos(angle)
 | 
			
		||||
		// For indexes corresponding to null cosine or sine, we make sure the value is zero
 | 
			
		||||
		// and not an epsilon. This allows for a much better accuracy for results close to zero.
 | 
			
		||||
		if i == sinCosPiIndex {
 | 
			
		||||
			sinAngle = 0.0
 | 
			
		||||
		} else if i == sinCosPiMul2Index {
 | 
			
		||||
			sinAngle = 0.0
 | 
			
		||||
		} else if i == sinCosPiMul05Index {
 | 
			
		||||
			sinAngle = 0.0
 | 
			
		||||
		} else if i == sinCosPiMul15Index {
 | 
			
		||||
			sinAngle = 0.0
 | 
			
		||||
		}
 | 
			
		||||
		sinTab[i] = sinAngle
 | 
			
		||||
		cosTab[i] = cosAngle
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// asin
 | 
			
		||||
	asinTab = make([]float64, asinTabsSize)
 | 
			
		||||
	asinDer1DivF1Tab = make([]float64, asinTabsSize)
 | 
			
		||||
	asinDer2DivF2Tab = make([]float64, asinTabsSize)
 | 
			
		||||
	asinDer3DivF3Tab = make([]float64, asinTabsSize)
 | 
			
		||||
	asinDer4DivF4Tab = make([]float64, asinTabsSize)
 | 
			
		||||
	for i := 0; i < asinTabsSize; i++ {
 | 
			
		||||
		// x: in [0,ASIN_MAX_VALUE_FOR_TABS].
 | 
			
		||||
		x := float64(i) * asinDelta
 | 
			
		||||
		asinTab[i] = math.Asin(x)
 | 
			
		||||
		oneMinusXSqInv := 1.0 / (1 - x*x)
 | 
			
		||||
		oneMinusXSqInv05 := math.Sqrt(oneMinusXSqInv)
 | 
			
		||||
		oneMinusXSqInv15 := oneMinusXSqInv05 * oneMinusXSqInv
 | 
			
		||||
		oneMinusXSqInv25 := oneMinusXSqInv15 * oneMinusXSqInv
 | 
			
		||||
		oneMinusXSqInv35 := oneMinusXSqInv25 * oneMinusXSqInv
 | 
			
		||||
		asinDer1DivF1Tab[i] = oneMinusXSqInv05
 | 
			
		||||
		asinDer2DivF2Tab[i] = (x * oneMinusXSqInv15) * oneDivF2
 | 
			
		||||
		asinDer3DivF3Tab[i] = ((1 + 2*x*x) * oneMinusXSqInv25) * oneDivF3
 | 
			
		||||
		asinDer4DivF4Tab[i] = ((5 + 2*x*(2+x*(5-2*x))) * oneMinusXSqInv35) * oneDivF4
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// earth radius
 | 
			
		||||
	a := 6378137.0
 | 
			
		||||
	b := 6356752.31420
 | 
			
		||||
	a2 := a * a
 | 
			
		||||
	b2 := b * b
 | 
			
		||||
	earthDiameterPerLatitude = make([]float64, radiusTabsSize)
 | 
			
		||||
	earthDiameterPerLatitude[0] = 2.0 * a / 1000
 | 
			
		||||
	earthDiameterPerLatitude[radiusTabsSize-1] = 2.0 * b / 1000
 | 
			
		||||
	for i := 1; i < radiusTabsSize-1; i++ {
 | 
			
		||||
		lat := math.Pi * float64(i) / (2*radiusTabsSize - 1)
 | 
			
		||||
		one := math.Pow(a2*math.Cos(lat), 2)
 | 
			
		||||
		two := math.Pow(b2*math.Sin(lat), 2)
 | 
			
		||||
		three := math.Pow(float64(a)*math.Cos(lat), 2)
 | 
			
		||||
		four := math.Pow(b*math.Sin(lat), 2)
 | 
			
		||||
		radius := math.Sqrt((one + two) / (three + four))
 | 
			
		||||
		earthDiameterPerLatitude[i] = 2 * radius / 1000
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// earthDiameter returns an estimation of the earth's diameter at the specified
 | 
			
		||||
// latitude in kilometers
 | 
			
		||||
func earthDiameter(lat float64) float64 {
 | 
			
		||||
	index := math.Mod(math.Abs(lat)*radiusIndexer+0.5, float64(len(earthDiameterPerLatitude)))
 | 
			
		||||
	if math.IsNaN(index) {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return earthDiameterPerLatitude[int(index)]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var pio2 = math.Pi / 2
 | 
			
		||||
 | 
			
		||||
func sin(a float64) float64 {
 | 
			
		||||
	return cos(a - pio2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// cos is a sloppy math (faster) implementation of math.Cos
 | 
			
		||||
func cos(a float64) float64 {
 | 
			
		||||
	if a < 0.0 {
 | 
			
		||||
		a = -a
 | 
			
		||||
	}
 | 
			
		||||
	if a > sinCosMaxValueForIntModulo {
 | 
			
		||||
		return math.Cos(a)
 | 
			
		||||
	}
 | 
			
		||||
	// index: possibly outside tables range.
 | 
			
		||||
	index := int(a*sinCosIndexer + 0.5)
 | 
			
		||||
	delta := (a - float64(index)*sinCosDeltaHi) - float64(index)*sinCosDeltaLo
 | 
			
		||||
	// Making sure index is within tables range.
 | 
			
		||||
	// Last value of each table is the same than first, so we ignore it (tabs size minus one) for modulo.
 | 
			
		||||
	index &= (sinCosTabsSize - 2) // index % (SIN_COS_TABS_SIZE-1)
 | 
			
		||||
	indexCos := cosTab[index]
 | 
			
		||||
	indexSin := sinTab[index]
 | 
			
		||||
	return indexCos + delta*(-indexSin+delta*(-indexCos*oneDivF2+delta*(indexSin*oneDivF3+delta*indexCos*oneDivF4)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// asin is a sloppy math (faster) implementation of math.Asin
 | 
			
		||||
func asin(a float64) float64 {
 | 
			
		||||
	var negateResult bool
 | 
			
		||||
	if a < 0 {
 | 
			
		||||
		a = -a
 | 
			
		||||
		negateResult = true
 | 
			
		||||
	}
 | 
			
		||||
	if a <= asinMaxValueForTabs {
 | 
			
		||||
		index := int(a*asinIndexer + 0.5)
 | 
			
		||||
		delta := a - float64(index)*asinDelta
 | 
			
		||||
		result := asinTab[index] + delta*(asinDer1DivF1Tab[index]+delta*(asinDer2DivF2Tab[index]+delta*(asinDer3DivF3Tab[index]+delta*asinDer4DivF4Tab[index])))
 | 
			
		||||
		if negateResult {
 | 
			
		||||
			return -result
 | 
			
		||||
		}
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
	// value > ASIN_MAX_VALUE_FOR_TABS, or value is NaN
 | 
			
		||||
	// This part is derived from fdlibm.
 | 
			
		||||
	if a < 1 {
 | 
			
		||||
		t := (1.0 - a) * 0.5
 | 
			
		||||
		p := t * (asinPs0 + t*(asinPs1+t*(asinPs2+t*(asinPs3+t*(asinPs4+t+asinPs5)))))
 | 
			
		||||
		q := 1.0 + t*(asinQs1+t*(asinQs2+t*(asinQs3+t*asinQs4)))
 | 
			
		||||
		s := math.Sqrt(t)
 | 
			
		||||
		z := s + s*(p/q)
 | 
			
		||||
		result := asinPio2Hi - ((z + z) - asinPio2Lo)
 | 
			
		||||
		if negateResult {
 | 
			
		||||
			return -result
 | 
			
		||||
		}
 | 
			
		||||
		return result
 | 
			
		||||
	}
 | 
			
		||||
	// value >= 1.0, or value is NaN
 | 
			
		||||
	if a == 1.0 {
 | 
			
		||||
		if negateResult {
 | 
			
		||||
			return -math.Pi / 2
 | 
			
		||||
		}
 | 
			
		||||
		return math.Pi / 2
 | 
			
		||||
	}
 | 
			
		||||
	return math.NaN()
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue