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
	}
	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
	}
	if a == 1.0 {
		if negateResult {
			return -math.Pi / 2
		}
		return math.Pi / 2
	}
	return math.NaN()
}
asin is a sloppy math (faster) implementation of math.Asin
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
var pio2Hi = math.Float64frombits(0x3FF921FB54400000)
var pio2Lo = math.Float64frombits(0x3DD0B4611A626331)
var asinPio2Hi = math.Float64frombits(0x3FF921FB54442D18)  
var asinPio2Lo = math.Float64frombits(0x3C91A62633145C07)  
var asinPs0 = math.Float64frombits(0x3fc5555555555555)     
var asinPs1 = math.Float64frombits(0xbfd4d61203eb6f7d)     
var asinPs2 = math.Float64frombits(0x3fc9c1550e884455)     
var asinPs3 = math.Float64frombits(0xbfa48228b5688f3b)     
var asinPs4 = math.Float64frombits(0x3f49efe07501b288)     
var asinPs5 = math.Float64frombits(0x3f023de10dfdf709)     
var asinQs1 = math.Float64frombits(0xc0033a271c8a2d4b)     
var asinQs2 = math.Float64frombits(0x40002ae59c598ac8)     
var asinQs3 = math.Float64frombits(0xbfe6066c1b8d0159)     
var asinQs4 = math.Float64frombits(0x3fb3b8c5b12e9282)     
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() {
	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 := float64(i)*sinCosDeltaHi + float64(i)*sinCosDeltaLo
		sinAngle := math.Sin(angle)
		cosAngle := math.Cos(angle)
		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
	}
	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 := 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
	}
	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
	}
}
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)
}
func cos(a float64) float64 {
	if a < 0.0 {
		a = -a
	}
	if a > sinCosMaxValueForIntModulo {
		return math.Cos(a)
	}
	index := int(a*sinCosIndexer + 0.5)
	delta := (a - float64(index)*sinCosDeltaHi) - float64(index)*sinCosDeltaLo
	index &= (sinCosTabsSize - 2)  
	indexCos := cosTab[index]
	indexSin := sinTab[index]
	return indexCos + delta*(-indexSin+delta*(-indexCos*oneDivF2+delta*(indexSin*oneDivF3+delta*indexCos*oneDivF4)))
}