mirror of
https://github.com/make-42/xyosc
synced 2025-01-18 10:47:10 +01:00
add vendor
This commit is contained in:
parent
091fdff06b
commit
d60dfeb0e4
24
vendor/github.com/chewxy/math32/.gitignore
generated
vendored
Normal file
24
vendor/github.com/chewxy/math32/.gitignore
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
25
vendor/github.com/chewxy/math32/LICENSE
generated
vendored
Normal file
25
vendor/github.com/chewxy/math32/LICENSE
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2021, Xuanyi Chew and the Go Authors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
7
vendor/github.com/chewxy/math32/README.md
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/README.md
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# math32 [![GoDoc](https://godoc.org/github.com/chewxy/math32?status.svg)](https://godoc.org/github.com/chewxy/math32)
|
||||
|
||||
A `float32` version of Go's math package. The majority of code in this library is a thin `float32` wrapper over the results of the `math` package that comes in the standard lib.
|
||||
|
||||
|
||||
The original code is lifted from the Go standard library which is governed by
|
||||
a BSD-style licence which can be found here: https://golang.org/LICENSE.
|
183
vendor/github.com/chewxy/math32/_exp_arm64.s
generated
vendored
Normal file
183
vendor/github.com/chewxy/math32/_exp_arm64.s
generated
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
//go:build !tinygo && !noasm
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#define Ln2Hi 6.9313812256e-01
|
||||
#define Ln2Lo 9.0580006145e-06
|
||||
#define Log2e 1.4426950216e+00
|
||||
#define Overflow 7.097827e+02
|
||||
#define Underflow -7.451332e+02
|
||||
#define Overflow2 1.024000e+03
|
||||
#define Underflow2 -1.0740e+03
|
||||
#define NearZero 0x317fffff // 2**-28
|
||||
#define PosInf 0x7f800000
|
||||
#define FracMask 0x07fffff
|
||||
#define C1 0x34000000 // 2**-23
|
||||
#define P1 1.6666667163e-01 // 0x3FC55555; 0x55555555
|
||||
#define P2 -2.7777778450e-03 // 0xBF66C16C; 0x16BEBD93
|
||||
#define P3 6.6137559770e-05 // 0x3F11566A; 0xAF25DE2C
|
||||
#define P4 -1.6533901999e-06 // 0xBEBBBD41; 0xC5D26BF1
|
||||
#define P5 4.1381369442e-08 // 0x3E663769; 0x72BEA4D0
|
||||
|
||||
// Exp returns e**x, the base-e exponential of x.
|
||||
// This is an assembly implementation of the method used for function Exp in file exp.go.
|
||||
//
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),$0-12
|
||||
FMOVS x+0(FP), F0 // F0 = x
|
||||
FCMPS F0, F0
|
||||
BNE isNaN // x = NaN, return NaN
|
||||
FMOVS $Overflow, F1
|
||||
FCMPS F1, F0
|
||||
BGT overflow // x > Overflow, return PosInf
|
||||
FMOVS $Underflow, F1
|
||||
FCMPS F1, F0
|
||||
BLT underflow // x < Underflow, return 0
|
||||
MOVW $NearZero, R0
|
||||
FMOVS R0, F2
|
||||
FABSS F0, F3
|
||||
FMOVS $1.0, F1 // F1 = 1.0
|
||||
FCMPS F2, F3
|
||||
BLT nearzero // fabs(x) < NearZero, return 1 + x
|
||||
// argument reduction, x = k*ln2 + r, |r| <= 0.5*ln2
|
||||
// computed as r = hi - lo for extra precision.
|
||||
FMOVS $Log2e, F2
|
||||
FMOVS $0.5, F3
|
||||
FNMSUBS F0, F3, F2, F4 // Log2e*x - 0.5
|
||||
FMADDS F0, F3, F2, F3 // Log2e*x + 0.5
|
||||
FCMPS $0.0, F0
|
||||
FCSELS LT, F4, F3, F3 // F3 = k
|
||||
FCVTZSS F3, R1 // R1 = int(k)
|
||||
SCVTFS R1, F3 // F3 = float32(int(k))
|
||||
FMOVS $Ln2Hi, F4 // F4 = Ln2Hi
|
||||
FMOVS $Ln2Lo, F5 // F5 = Ln2Lo
|
||||
FMSUBS F3, F0, F4, F4 // F4 = hi = x - float32(int(k))*Ln2Hi
|
||||
FMULS F3, F5 // F5 = lo = float32(int(k)) * Ln2Lo
|
||||
FSUBS F5, F4, F6 // F6 = r = hi - lo
|
||||
FMULS F6, F6, F7 // F7 = t = r * r
|
||||
// compute y
|
||||
FMOVS $P5, F8 // F8 = P5
|
||||
FMOVS $P4, F9 // F9 = P4
|
||||
FMADDS F7, F9, F8, F13 // P4+t*P5
|
||||
FMOVS $P3, F10 // F10 = P3
|
||||
FMADDS F7, F10, F13, F13 // P3+t*(P4+t*P5)
|
||||
FMOVS $P2, F11 // F11 = P2
|
||||
FMADDS F7, F11, F13, F13 // P2+t*(P3+t*(P4+t*P5))
|
||||
FMOVS $P1, F12 // F12 = P1
|
||||
FMADDS F7, F12, F13, F13 // P1+t*(P2+t*(P3+t*(P4+t*P5)))
|
||||
FMSUBS F7, F6, F13, F13 // F13 = c = r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
|
||||
FMOVS $2.0, F14
|
||||
FSUBS F13, F14
|
||||
FMULS F6, F13, F15
|
||||
FDIVS F14, F15 // F15 = (r*c)/(2-c)
|
||||
FSUBS F15, F5, F15 // lo-(r*c)/(2-c)
|
||||
FSUBS F4, F15, F15 // (lo-(r*c)/(2-c))-hi
|
||||
FSUBS F15, F1, F16 // F16 = y = 1-((lo-(r*c)/(2-c))-hi)
|
||||
// inline Ldexp(y, k), benefit:
|
||||
// 1, no parameter pass overhead.
|
||||
// 2, skip unnecessary checks for Inf/NaN/Zero
|
||||
FMOVS F16, R0
|
||||
ANDS $FracMask, R0, R2 // fraction
|
||||
LSRW $23, R0, R5 // exponent
|
||||
ADDS R1, R5 // R1 = int(k)
|
||||
CMPW $1, R5
|
||||
BGE normal
|
||||
ADDS $23, R5 // denormal
|
||||
MOVW $C1, R8
|
||||
FMOVS R8, F1 // m = 2**-23
|
||||
normal:
|
||||
ORRW R5<<23, R2, R0
|
||||
FMOVS R0, F0
|
||||
FMULS F1, F0 // return m * x
|
||||
FMOVS F0, ret+8(FP)
|
||||
RET
|
||||
nearzero:
|
||||
FADDS F1, F0
|
||||
isNaN:
|
||||
FMOVS F0, ret+8(FP)
|
||||
RET
|
||||
underflow:
|
||||
MOVW ZR, ret+8(FP)
|
||||
RET
|
||||
overflow:
|
||||
MOVW $PosInf, R0
|
||||
MOVW R0, ret+8(FP)
|
||||
RET
|
||||
|
||||
|
||||
// Exp2 returns 2**x, the base-2 exponential of x.
|
||||
// This is an assembly implementation of the method used for function Exp2 in file exp.go.
|
||||
//
|
||||
// func archExp2(x float32) float32
|
||||
TEXT ·archExp2(SB),$0-12 // Is this correct?
|
||||
FMOVS x+0(FP), F0 // F0 = x
|
||||
FCMPS F0, F0
|
||||
BNE isNaN // x = NaN, return NaN
|
||||
FMOVS $Overflow2, F1
|
||||
FCMPS F1, F0
|
||||
BGT overflow // x > Overflow, return PosInf
|
||||
FMOVS $Underflow2, F1
|
||||
FCMPS F1, F0
|
||||
BLT underflow // x < Underflow, return 0
|
||||
// argument reduction; x = r*lg(e) + k with |r| <= ln(2)/2
|
||||
// computed as r = hi - lo for extra precision.
|
||||
FMOVS $0.5, F2
|
||||
FSUBS F2, F0, F3 // x + 0.5
|
||||
FADDS F2, F0, F4 // x - 0.5
|
||||
FCMPS $0.0, F0
|
||||
FCSELS LT, F3, F4, F3 // F3 = k
|
||||
FCVTZSS F3, R1 // R1 = int(k)
|
||||
SCVTFS R1, F3 // F3 = float32(int(k))
|
||||
FSUBS F3, F0, F3 // t = x - float32(int(k))
|
||||
FMOVS $Ln2Hi, F4 // F4 = Ln2Hi
|
||||
FMOVS $Ln2Lo, F5 // F5 = Ln2Lo
|
||||
FMULS F3, F4 // F4 = hi = t * Ln2Hi
|
||||
FNMULS F3, F5 // F5 = lo = -t * Ln2Lo
|
||||
FSUBS F5, F4, F6 // F6 = r = hi - lo
|
||||
FMULS F6, F6, F7 // F7 = t = r * r
|
||||
// compute y
|
||||
FMOVS $P5, F8 // F8 = P5
|
||||
FMOVS $P4, F9 // F9 = P4
|
||||
FMADDS F7, F9, F8, F13 // P4+t*P5
|
||||
FMOVS $P3, F10 // F10 = P3
|
||||
FMADDS F7, F10, F13, F13 // P3+t*(P4+t*P5)
|
||||
FMOVS $P2, F11 // F11 = P2
|
||||
FMADDS F7, F11, F13, F13 // P2+t*(P3+t*(P4+t*P5))
|
||||
FMOVS $P1, F12 // F12 = P1
|
||||
FMADDS F7, F12, F13, F13 // P1+t*(P2+t*(P3+t*(P4+t*P5)))
|
||||
FMSUBS F7, F6, F13, F13 // F13 = c = r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
|
||||
FMOVS $2.0, F14
|
||||
FSUBS F13, F14
|
||||
FMULS F6, F13, F15
|
||||
FDIVS F14, F15 // F15 = (r*c)/(2-c)
|
||||
FMOVS $1.0, F1 // F1 = 1.0
|
||||
FSUBS F15, F5, F15 // lo-(r*c)/(2-c)
|
||||
FSUBS F4, F15, F15 // (lo-(r*c)/(2-c))-hi
|
||||
FSUBS F15, F1, F16 // F16 = y = 1-((lo-(r*c)/(2-c))-hi)
|
||||
// inline Ldexp(y, k), benefit:
|
||||
// 1, no parameter pass overhead.
|
||||
// 2, skip unnecessary checks for Inf/NaN/Zero
|
||||
FMOVS F16, R0
|
||||
ANDS $FracMask, R0, R2 // fraction
|
||||
LSRW $23, R0, R5 // exponent
|
||||
ADDS R1, R5 // R1 = int(k)
|
||||
CMPW $1, R5
|
||||
BGE normal
|
||||
ADDS $23, R5 // denormal
|
||||
MOVW $C1, R8
|
||||
FMOVS R8, F1 // m = 2**-52
|
||||
normal:
|
||||
ORRW R5<<23, R2, R0
|
||||
FMOVS R0, F0
|
||||
FMULS F1, F0 // return m * x
|
||||
isNaN:
|
||||
FMOVS F0, ret+8(FP)
|
||||
RET
|
||||
underflow:
|
||||
MOVW ZR, ret+8(FP)
|
||||
RET
|
||||
overflow:
|
||||
MOVW $PosInf, R0
|
||||
MOVW R0, ret+8(FP)
|
||||
RET
|
22
vendor/github.com/chewxy/math32/_stubs_risc64.s
generated
vendored
Normal file
22
vendor/github.com/chewxy/math32/_stubs_risc64.s
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
B ·exp(SB)
|
||||
|
||||
// func archExp2(x float32) float32
|
||||
TEXT ·archExp2(SB),NOSPLIT,$0
|
||||
B ·exp2(SB)
|
||||
|
||||
// func archLog(x float32) float32
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
B ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
B ·remainder(SB)
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
B ·sqrt(SB)
|
10
vendor/github.com/chewxy/math32/abs.go
generated
vendored
Normal file
10
vendor/github.com/chewxy/math32/abs.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
package math32
|
||||
|
||||
// Abs returns the absolute value of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Abs(±Inf) = +Inf
|
||||
// Abs(NaN) = NaN
|
||||
func Abs(x float32) float32 {
|
||||
return Float32frombits(Float32bits(x) &^ (1 << 31))
|
||||
}
|
9
vendor/github.com/chewxy/math32/acos.go
generated
vendored
Normal file
9
vendor/github.com/chewxy/math32/acos.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
package math32
|
||||
|
||||
// Acos returns the arccosine, in radians, of x.
|
||||
//
|
||||
// Special case is:
|
||||
// Acos(x) = NaN if x < -1 or x > 1
|
||||
func Acos(x float32) float32 {
|
||||
return Pi/2 - Asin(x)
|
||||
}
|
53
vendor/github.com/chewxy/math32/acosh.go
generated
vendored
Normal file
53
vendor/github.com/chewxy/math32/acosh.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package math32
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below are from FreeBSD's /usr/src/lib/msun/src/e_acosh.c
|
||||
// and came with this notice. The go code is a simplified
|
||||
// version of the original C.
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
//
|
||||
// __ieee754_acosh(x)
|
||||
// Method :
|
||||
// Based on
|
||||
// acosh(x) = log [ x + sqrt(x*x-1) ]
|
||||
// we have
|
||||
// acosh(x) := log(x)+ln2, if x is large; else
|
||||
// acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
|
||||
// acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
|
||||
//
|
||||
// Special cases:
|
||||
// acosh(x) is NaN with signal if x<1.
|
||||
// acosh(NaN) is NaN without signal.
|
||||
//
|
||||
|
||||
// Acosh returns the inverse hyperbolic cosine of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Acosh(+Inf) = +Inf
|
||||
// Acosh(x) = NaN if x < 1
|
||||
// Acosh(NaN) = NaN
|
||||
func Acosh(x float32) float32 {
|
||||
const Large = 1 << 28 // 2**28
|
||||
// first case is special case
|
||||
switch {
|
||||
case x < 1 || IsNaN(x):
|
||||
return NaN()
|
||||
case x == 1:
|
||||
return 0
|
||||
case x >= Large:
|
||||
return Log(x) + Ln2 // x > 2**28
|
||||
case x > 2:
|
||||
return Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2
|
||||
}
|
||||
t := x - 1
|
||||
return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1
|
||||
}
|
27
vendor/github.com/chewxy/math32/asin.go
generated
vendored
Normal file
27
vendor/github.com/chewxy/math32/asin.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package math32
|
||||
|
||||
func Asin(x float32) float32 {
|
||||
if x == 0 {
|
||||
return x // special case
|
||||
}
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
if x > 1 {
|
||||
return NaN() // special case
|
||||
}
|
||||
|
||||
temp := Sqrt(1 - x*x)
|
||||
if x > 0.7 {
|
||||
temp = Pi/2 - satan(temp/x)
|
||||
} else {
|
||||
temp = satan(x / temp)
|
||||
}
|
||||
|
||||
if sign {
|
||||
temp = -temp
|
||||
}
|
||||
return temp
|
||||
}
|
65
vendor/github.com/chewxy/math32/asinh.go
generated
vendored
Normal file
65
vendor/github.com/chewxy/math32/asinh.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
package math32
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below are from FreeBSD's /usr/src/lib/msun/src/s_asinh.c
|
||||
// and came with this notice. The go code is a simplified
|
||||
// version of the original C.
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
//
|
||||
// asinh(x)
|
||||
// Method :
|
||||
// Based on
|
||||
// asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
|
||||
// we have
|
||||
// asinh(x) := x if 1+x*x=1,
|
||||
// := sign(x)*(log(x)+ln2)) for large |x|, else
|
||||
// := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
|
||||
// := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2)))
|
||||
//
|
||||
|
||||
// Asinh returns the inverse hyperbolic sine of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Asinh(±0) = ±0
|
||||
// Asinh(±Inf) = ±Inf
|
||||
// Asinh(NaN) = NaN
|
||||
func Asinh(x float32) float32 {
|
||||
const (
|
||||
Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF
|
||||
NearZero = 1.0 / (1 << 28) // 2**-28
|
||||
Large = 1 << 28 // 2**28
|
||||
)
|
||||
// special cases
|
||||
if IsNaN(x) || IsInf(x, 0) {
|
||||
return x
|
||||
}
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
var temp float32
|
||||
switch {
|
||||
case x > Large:
|
||||
temp = Log(x) + Ln2 // |x| > 2**28
|
||||
case x > 2:
|
||||
temp = Log(2*x + 1/(Sqrt(x*x+1)+x)) // 2**28 > |x| > 2.0
|
||||
case x < NearZero:
|
||||
temp = x // |x| < 2**-28
|
||||
default:
|
||||
temp = Log1p(x + x*x/(1+Sqrt(1+x*x))) // 2.0 > |x| > 2**-28
|
||||
}
|
||||
if sign {
|
||||
temp = -temp
|
||||
}
|
||||
return temp
|
||||
}
|
90
vendor/github.com/chewxy/math32/atan.go
generated
vendored
Normal file
90
vendor/github.com/chewxy/math32/atan.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
package math32
|
||||
|
||||
func Atan(x float32) float32 {
|
||||
if x == 0 {
|
||||
return x
|
||||
}
|
||||
if x > 0 {
|
||||
return satan(x)
|
||||
}
|
||||
return -satan(-x)
|
||||
}
|
||||
|
||||
// The original C code, the long comment, and the constants below were
|
||||
// from http://netlib.sandia.gov/cephes/cmath/atan.c, available from
|
||||
// http://www.netlib.org/cephes/cmath.tgz.
|
||||
// The go code is a version of the original C.
|
||||
//
|
||||
// atan.c
|
||||
// Inverse circular tangent (arctangent)
|
||||
//
|
||||
// SYNOPSIS:
|
||||
// double x, y, atan();
|
||||
// y = atan( x );
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Returns radian angle between -pi/2 and +pi/2 whose tangent is x.
|
||||
//
|
||||
// Range reduction is from three intervals into the interval from zero to 0.66.
|
||||
// The approximant uses a rational function of degree 4/5 of the form
|
||||
// x + x**3 P(x)/Q(x).
|
||||
//
|
||||
// ACCURACY:
|
||||
// Relative error:
|
||||
// arithmetic domain # trials peak rms
|
||||
// DEC -10, 10 50000 2.4e-17 8.3e-18
|
||||
// IEEE -10, 10 10^6 1.8e-16 5.0e-17
|
||||
//
|
||||
// Cephes Math Library Release 2.8: June, 2000
|
||||
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
|
||||
//
|
||||
// The readme file at http://netlib.sandia.gov/cephes/ says:
|
||||
// Some software in this archive may be from the book _Methods and
|
||||
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
|
||||
// International, 1989) or from the Cephes Mathematical Library, a
|
||||
// commercial product. In either event, it is copyrighted by the author.
|
||||
// What you see here may be used freely but it comes with no support or
|
||||
// guarantee.
|
||||
//
|
||||
// The two known misprints in the book are repaired here in the
|
||||
// source listings for the gamma function and the incomplete beta
|
||||
// integral.
|
||||
//
|
||||
// Stephen L. Moshier
|
||||
// moshier@na-net.ornl.gov
|
||||
|
||||
// xatan evaluates a series valid in the range [0, 0.66].
|
||||
func xatan(x float32) float32 {
|
||||
const (
|
||||
P0 = -8.750608600031904122785e-01
|
||||
P1 = -1.615753718733365076637e+01
|
||||
P2 = -7.500855792314704667340e+01
|
||||
P3 = -1.228866684490136173410e+02
|
||||
P4 = -6.485021904942025371773e+01
|
||||
Q0 = +2.485846490142306297962e+01
|
||||
Q1 = +1.650270098316988542046e+02
|
||||
Q2 = +4.328810604912902668951e+02
|
||||
Q3 = +4.853903996359136964868e+02
|
||||
Q4 = +1.945506571482613964425e+02
|
||||
)
|
||||
z := x * x
|
||||
z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4)
|
||||
z = x*z + x
|
||||
return z
|
||||
}
|
||||
|
||||
// satan reduces its argument (known to be positive)
|
||||
// to the range [0, 0.66] and calls xatan.
|
||||
func satan(x float32) float32 {
|
||||
const (
|
||||
Morebits float32 = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits
|
||||
Tan3pio8 float32 = 2.41421356237309504880 // tan(3*pi/8)
|
||||
)
|
||||
if x <= 0.66 {
|
||||
return xatan(x)
|
||||
}
|
||||
if x > Tan3pio8 {
|
||||
return Pi/2 - xatan(1/x) + Morebits
|
||||
}
|
||||
return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits
|
||||
}
|
62
vendor/github.com/chewxy/math32/atan2.go
generated
vendored
Normal file
62
vendor/github.com/chewxy/math32/atan2.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package math32
|
||||
|
||||
// Atan2 returns the arc tangent of y/x, using the signs of the two to determine the quadrant of the return value.
|
||||
// Special cases are (in order):
|
||||
// Atan2(y, NaN) = NaN
|
||||
// Atan2(NaN, x) = NaN
|
||||
// Atan2(+0, x>=0) = +0
|
||||
// Atan2(-0, x>=0) = -0
|
||||
// Atan2(+0, x<=-0) = +Pi
|
||||
// Atan2(-0, x<=-0) = -Pi
|
||||
// Atan2(y>0, 0) = +Pi/2
|
||||
// Atan2(y<0, 0) = -Pi/2
|
||||
// Atan2(+Inf, +Inf) = +Pi/4
|
||||
// Atan2(-Inf, +Inf) = -Pi/4
|
||||
// Atan2(+Inf, -Inf) = 3Pi/4
|
||||
// Atan2(-Inf, -Inf) = -3Pi/4
|
||||
// Atan2(y, +Inf) = 0
|
||||
// Atan2(y>0, -Inf) = +Pi
|
||||
// Atan2(y<0, -Inf) = -Pi
|
||||
// Atan2(+Inf, x) = +Pi/2
|
||||
// Atan2(-Inf, x) = -Pi/2
|
||||
func Atan2(y, x float32) float32 {
|
||||
// special cases
|
||||
switch {
|
||||
case IsNaN(y) || IsNaN(x):
|
||||
return NaN()
|
||||
case y == 0:
|
||||
if x >= 0 && !Signbit(x) {
|
||||
return Copysign(0, y)
|
||||
}
|
||||
return Copysign(Pi, y)
|
||||
case x == 0:
|
||||
return Copysign(Pi/2, y)
|
||||
case IsInf(x, 0):
|
||||
if IsInf(x, 1) {
|
||||
switch {
|
||||
case IsInf(y, 0):
|
||||
return Copysign(Pi/4, y)
|
||||
default:
|
||||
return Copysign(0, y)
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case IsInf(y, 0):
|
||||
return Copysign(3*Pi/4, y)
|
||||
default:
|
||||
return Copysign(Pi, y)
|
||||
}
|
||||
case IsInf(y, 0):
|
||||
return Copysign(Pi/2, y)
|
||||
}
|
||||
|
||||
// Call atan and determine the quadrant.
|
||||
q := Atan(y / x)
|
||||
if x < 0 {
|
||||
if q <= 0 {
|
||||
return q + Pi
|
||||
}
|
||||
return q - Pi
|
||||
}
|
||||
return q
|
||||
}
|
73
vendor/github.com/chewxy/math32/atanh.go
generated
vendored
Normal file
73
vendor/github.com/chewxy/math32/atanh.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
package math32
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below are from FreeBSD's /usr/src/lib/msun/src/e_atanh.c
|
||||
// and came with this notice. The go code is a simplified
|
||||
// version of the original C.
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
//
|
||||
// __ieee754_atanh(x)
|
||||
// Method :
|
||||
// 1. Reduce x to positive by atanh(-x) = -atanh(x)
|
||||
// 2. For x>=0.5
|
||||
// 1 2x x
|
||||
// atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
|
||||
// 2 1 - x 1 - x
|
||||
//
|
||||
// For x<0.5
|
||||
// atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
|
||||
//
|
||||
// Special cases:
|
||||
// atanh(x) is NaN if |x| > 1 with signal;
|
||||
// atanh(NaN) is that NaN with no signal;
|
||||
// atanh(+-1) is +-INF with signal.
|
||||
//
|
||||
|
||||
// Atanh returns the inverse hyperbolic tangent of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Atanh(1) = +Inf
|
||||
// Atanh(±0) = ±0
|
||||
// Atanh(-1) = -Inf
|
||||
// Atanh(x) = NaN if x < -1 or x > 1
|
||||
// Atanh(NaN) = NaN
|
||||
func Atanh(x float32) float32 {
|
||||
const NearZero = 1.0 / (1 << 28) // 2**-28
|
||||
// special cases
|
||||
switch {
|
||||
case x < -1 || x > 1 || IsNaN(x):
|
||||
return NaN()
|
||||
case x == 1:
|
||||
return Inf(1)
|
||||
case x == -1:
|
||||
return Inf(-1)
|
||||
}
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
var temp float32
|
||||
switch {
|
||||
case x < NearZero:
|
||||
temp = x
|
||||
case x < 0.5:
|
||||
temp = x + x
|
||||
temp = 0.5 * Log1p(temp+temp*x/(1-x))
|
||||
default:
|
||||
temp = 0.5 * Log1p((x+x)/(1-x))
|
||||
}
|
||||
if sign {
|
||||
temp = -temp
|
||||
}
|
||||
return temp
|
||||
}
|
58
vendor/github.com/chewxy/math32/bits.go
generated
vendored
Normal file
58
vendor/github.com/chewxy/math32/bits.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
package math32
|
||||
|
||||
const (
|
||||
uvnan = 0x7FE00000
|
||||
uvinf = 0x7F800000
|
||||
uvone = 0x3f800000
|
||||
uvneginf = 0xFF800000
|
||||
mask = 0xFF
|
||||
shift = 32 - 8 - 1
|
||||
bias = 127
|
||||
signMask = 1 << 31
|
||||
fracMask = 1<<shift - 1
|
||||
)
|
||||
|
||||
// Inf returns positive infinity if sign >= 0, negative infinity if sign < 0.
|
||||
func Inf(sign int) float32 {
|
||||
var v uint32
|
||||
if sign >= 0 {
|
||||
v = uvinf
|
||||
} else {
|
||||
v = uvneginf
|
||||
}
|
||||
return Float32frombits(v)
|
||||
}
|
||||
|
||||
// NaN returns an IEEE 754 ``not-a-number'' value.
|
||||
func NaN() float32 { return Float32frombits(uvnan) }
|
||||
|
||||
// IsNaN reports whether f is an IEEE 754 ``not-a-number'' value.
|
||||
func IsNaN(f float32) (is bool) {
|
||||
// IEEE 754 says that only NaNs satisfy f != f.
|
||||
// To avoid the floating-point hardware, could use:
|
||||
// x := Float32bits(f)
|
||||
// return uint32(x>>shift)&mask == mask && x != uvinf && x != uvneginf
|
||||
return f != f
|
||||
}
|
||||
|
||||
// IsInf reports whether f is an infinity, according to sign.
|
||||
// If sign > 0, IsInf reports whether f is positive infinity.
|
||||
// If sign < 0, IsInf reports whether f is negative infinity.
|
||||
// If sign == 0, IsInf reports whether f is either infinity.
|
||||
func IsInf(f float32, sign int) bool {
|
||||
// Test for infinity by comparing against maximum float.
|
||||
// To avoid the floating-point hardware, could use:
|
||||
// x := Float32bits(f)
|
||||
// return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf
|
||||
return sign >= 0 && f > MaxFloat32 || sign <= 0 && f < -MaxFloat32
|
||||
}
|
||||
|
||||
// normalize returns a normal number y and exponent exp
|
||||
// satisfying x == y × 2**exp. It assumes x is finite and non-zero.
|
||||
func normalize(x float32) (y float32, exp int) {
|
||||
const SmallestNormal = 1.1754943508222875079687365e-38 // 2**-(127 - 1)
|
||||
if Abs(x) < SmallestNormal {
|
||||
return x * (1 << shift), -shift
|
||||
}
|
||||
return x, 0
|
||||
}
|
7
vendor/github.com/chewxy/math32/cbrt.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/cbrt.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Cbrt(x float32) float32 {
|
||||
return float32(math.Cbrt(float64(x)))
|
||||
}
|
42
vendor/github.com/chewxy/math32/const.go
generated
vendored
Normal file
42
vendor/github.com/chewxy/math32/const.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
package math32
|
||||
|
||||
// Mathematical constants.
|
||||
const (
|
||||
E = float32(2.71828182845904523536028747135266249775724709369995957496696763) // http://oeis.org/A001113
|
||||
Pi = float32(3.14159265358979323846264338327950288419716939937510582097494459) // http://oeis.org/A000796
|
||||
Phi = float32(1.61803398874989484820458683436563811772030917980576286213544862) // http://oeis.org/A001622
|
||||
|
||||
Sqrt2 = float32(1.41421356237309504880168872420969807856967187537694807317667974) // http://oeis.org/A002193
|
||||
SqrtE = float32(1.64872127070012814684865078781416357165377610071014801157507931) // http://oeis.org/A019774
|
||||
SqrtPi = float32(1.77245385090551602729816748334114518279754945612238712821380779) // http://oeis.org/A002161
|
||||
SqrtPhi = float32(1.27201964951406896425242246173749149171560804184009624861664038) // http://oeis.org/A139339
|
||||
|
||||
Ln2 = float32(0.693147180559945309417232121458176568075500134360255254120680009) // http://oeis.org/A002162
|
||||
Log2E = float32(1 / Ln2)
|
||||
Ln10 = float32(2.30258509299404568401799145468436420760110148862877297603332790) // http://oeis.org/A002392
|
||||
Log10E = float32(1 / Ln10)
|
||||
)
|
||||
|
||||
// Floating-point limit values.
|
||||
// Max is the largest finite value representable by the type.
|
||||
// SmallestNonzero is the smallest positive, non-zero value representable by the type.
|
||||
const (
|
||||
MaxFloat32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23
|
||||
SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)
|
||||
)
|
||||
|
||||
// Integer limit values.
|
||||
const (
|
||||
MaxInt8 = 1<<7 - 1
|
||||
MinInt8 = -1 << 7
|
||||
MaxInt16 = 1<<15 - 1
|
||||
MinInt16 = -1 << 15
|
||||
MaxInt32 = 1<<31 - 1
|
||||
MinInt32 = -1 << 31
|
||||
MaxInt64 = 1<<63 - 1
|
||||
MinInt64 = -1 << 63
|
||||
MaxUint8 = 1<<8 - 1
|
||||
MaxUint16 = 1<<16 - 1
|
||||
MaxUint32 = 1<<32 - 1
|
||||
MaxUint64 = 1<<64 - 1
|
||||
)
|
8
vendor/github.com/chewxy/math32/copysign.go
generated
vendored
Normal file
8
vendor/github.com/chewxy/math32/copysign.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Copysign(x, y float32) float32 {
|
||||
const sign = 1 << 31
|
||||
return math.Float32frombits(math.Float32bits(x)&^sign | math.Float32bits(y)&sign)
|
||||
}
|
10
vendor/github.com/chewxy/math32/cosh.go
generated
vendored
Normal file
10
vendor/github.com/chewxy/math32/cosh.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
package math32
|
||||
|
||||
func Cosh(x float32) float32 {
|
||||
x = Abs(x)
|
||||
if x > 21 {
|
||||
return Exp(x) * 0.5
|
||||
}
|
||||
ex := Exp(x)
|
||||
return (ex + 1/ex) * 0.5
|
||||
}
|
77
vendor/github.com/chewxy/math32/dim.go
generated
vendored
Normal file
77
vendor/github.com/chewxy/math32/dim.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
package math32
|
||||
|
||||
// Dim returns the maximum of x-y or 0.
|
||||
//
|
||||
// Special cases are:
|
||||
//
|
||||
// Dim(+Inf, +Inf) = NaN
|
||||
// Dim(-Inf, -Inf) = NaN
|
||||
// Dim(x, NaN) = Dim(NaN, x) = NaN
|
||||
func Dim(x, y float32) float32 {
|
||||
return dim(x, y)
|
||||
}
|
||||
|
||||
func dim(x, y float32) float32 {
|
||||
return max(x-y, 0)
|
||||
}
|
||||
|
||||
// Max returns the larger of x or y.
|
||||
//
|
||||
// Special cases are:
|
||||
//
|
||||
// Max(x, +Inf) = Max(+Inf, x) = +Inf
|
||||
// Max(x, NaN) = Max(NaN, x) = NaN
|
||||
// Max(+0, ±0) = Max(±0, +0) = +0
|
||||
// Max(-0, -0) = -0
|
||||
func Max(x, y float32) float32 {
|
||||
return max(x, y)
|
||||
}
|
||||
|
||||
func max(x, y float32) float32 {
|
||||
// special cases
|
||||
switch {
|
||||
case IsInf(x, 1) || IsInf(y, 1):
|
||||
return Inf(1)
|
||||
case IsNaN(x) || IsNaN(y):
|
||||
return NaN()
|
||||
case x == 0 && x == y:
|
||||
if Signbit(x) {
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
if x > y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// Min returns the smaller of x or y.
|
||||
//
|
||||
// Special cases are:
|
||||
//
|
||||
// Min(x, -Inf) = Min(-Inf, x) = -Inf
|
||||
// Min(x, NaN) = Min(NaN, x) = NaN
|
||||
// Min(-0, ±0) = Min(±0, -0) = -0
|
||||
func Min(x, y float32) float32 {
|
||||
return min(x, y)
|
||||
}
|
||||
|
||||
func min(x, y float32) float32 {
|
||||
// special cases
|
||||
switch {
|
||||
case IsInf(x, -1) || IsInf(y, -1):
|
||||
return Inf(-1)
|
||||
case IsNaN(x) || IsNaN(y):
|
||||
return NaN()
|
||||
case x == 0 && x == y:
|
||||
if Signbit(x) {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
34
vendor/github.com/chewxy/math32/doc.go
generated
vendored
Normal file
34
vendor/github.com/chewxy/math32/doc.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Package math32 provides basic constants and mathematical functions for float32 types.
|
||||
|
||||
At its core, it's mostly just a wrapper in form of float32(math.XXX). This applies to the following functions:
|
||||
Acos
|
||||
Acosh
|
||||
Asin
|
||||
Asinh
|
||||
Atan
|
||||
Atan2
|
||||
Atanh
|
||||
Cbrt
|
||||
Cos
|
||||
Cosh
|
||||
Erfc
|
||||
Gamma
|
||||
J0
|
||||
J1
|
||||
Jn
|
||||
Log10
|
||||
Log1p
|
||||
Log2
|
||||
Logb
|
||||
Pow10
|
||||
Sin
|
||||
Sinh
|
||||
Tan
|
||||
Y0
|
||||
Y1
|
||||
|
||||
Everything else is a float32 implementation. Implementation schedule is sporadic an uncertain. But eventually all functions will be replaced
|
||||
|
||||
*/
|
||||
package math32
|
7
vendor/github.com/chewxy/math32/erf.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/erf.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Erf(x float32) float32 {
|
||||
return float32(math.Erf(float64(x)))
|
||||
}
|
7
vendor/github.com/chewxy/math32/erfc.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/erfc.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Erfc(x float32) float32 {
|
||||
return float32(math.Erfc(float64(x)))
|
||||
}
|
122
vendor/github.com/chewxy/math32/exp.go
generated
vendored
Normal file
122
vendor/github.com/chewxy/math32/exp.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
package math32
|
||||
|
||||
func Exp(x float32) float32 {
|
||||
if haveArchExp {
|
||||
return archExp(x)
|
||||
}
|
||||
return exp(x)
|
||||
}
|
||||
|
||||
func exp(x float32) float32 {
|
||||
const (
|
||||
Ln2Hi = float32(6.9313812256e-01)
|
||||
Ln2Lo = float32(9.0580006145e-06)
|
||||
Log2e = float32(1.4426950216e+00)
|
||||
|
||||
Overflow = 7.09782712893383973096e+02
|
||||
Underflow = -7.45133219101941108420e+02
|
||||
NearZero = 1.0 / (1 << 28) // 2**-28
|
||||
|
||||
LogMax = 0x42b2d4fc // The bitmask of log(FLT_MAX), rounded down. This value is the largest input that can be passed to exp() without producing overflow.
|
||||
LogMin = 0x42aeac50 // The bitmask of |log(REAL_FLT_MIN)|, rounding down
|
||||
|
||||
)
|
||||
// hx := Float32bits(x) & uint32(0x7fffffff)
|
||||
|
||||
// special cases
|
||||
switch {
|
||||
case IsNaN(x) || IsInf(x, 1):
|
||||
return x
|
||||
case IsInf(x, -1):
|
||||
return 0
|
||||
case x > Overflow:
|
||||
return Inf(1)
|
||||
case x < Underflow:
|
||||
// case hx > LogMax:
|
||||
// return Inf(1)
|
||||
// case x < 0 && hx > LogMin:
|
||||
return 0
|
||||
case -NearZero < x && x < NearZero:
|
||||
return 1 + x
|
||||
}
|
||||
|
||||
// reduce; computed as r = hi - lo for extra precision.
|
||||
var k int
|
||||
switch {
|
||||
case x < 0:
|
||||
k = int(Log2e*x - 0.5)
|
||||
case x > 0:
|
||||
k = int(Log2e*x + 0.5)
|
||||
}
|
||||
hi := x - float32(k)*Ln2Hi
|
||||
lo := float32(k) * Ln2Lo
|
||||
|
||||
// compute
|
||||
return expmulti(hi, lo, k)
|
||||
}
|
||||
|
||||
// Exp2 returns 2**x, the base-2 exponential of x.
|
||||
//
|
||||
// Special cases are the same as Exp.
|
||||
func Exp2(x float32) float32 {
|
||||
if haveArchExp2 {
|
||||
return archExp2(x)
|
||||
}
|
||||
return exp2(x)
|
||||
}
|
||||
|
||||
func exp2(x float32) float32 {
|
||||
const (
|
||||
Ln2Hi = 6.9313812256e-01
|
||||
Ln2Lo = 9.0580006145e-06
|
||||
|
||||
Overflow = 1.0239999999999999e+03
|
||||
Underflow = -1.0740e+03
|
||||
)
|
||||
|
||||
// special cases
|
||||
switch {
|
||||
case IsNaN(x) || IsInf(x, 1):
|
||||
return x
|
||||
case IsInf(x, -1):
|
||||
return 0
|
||||
case x > Overflow:
|
||||
return Inf(1)
|
||||
case x < Underflow:
|
||||
return 0
|
||||
}
|
||||
|
||||
// argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
|
||||
// computed as r = hi - lo for extra precision.
|
||||
var k int
|
||||
switch {
|
||||
case x > 0:
|
||||
k = int(x + 0.5)
|
||||
case x < 0:
|
||||
k = int(x - 0.5)
|
||||
}
|
||||
t := x - float32(k)
|
||||
hi := t * Ln2Hi
|
||||
lo := -t * Ln2Lo
|
||||
|
||||
// compute
|
||||
return expmulti(hi, lo, k)
|
||||
}
|
||||
|
||||
// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
|
||||
func expmulti(hi, lo float32, k int) float32 {
|
||||
const (
|
||||
P1 = float32(1.6666667163e-01) /* 0x3e2aaaab */
|
||||
P2 = float32(-2.7777778450e-03) /* 0xbb360b61 */
|
||||
P3 = float32(6.6137559770e-05) /* 0x388ab355 */
|
||||
P4 = float32(-1.6533901999e-06) /* 0xb5ddea0e */
|
||||
P5 = float32(4.1381369442e-08) /* 0x3331bb4c */
|
||||
)
|
||||
|
||||
r := hi - lo
|
||||
t := r * r
|
||||
c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
|
||||
y := 1 - ((lo - (r*c)/(2-c)) - hi)
|
||||
// TODO(rsc): make sure Ldexp can handle boundary k
|
||||
return Ldexp(y, k)
|
||||
}
|
14
vendor/github.com/chewxy/math32/exp2_asm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/exp2_asm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !noasm && !tinygo && (amd64 || 386 || arm || ppc64le || wasm)
|
||||
// +build !noasm
|
||||
// +build !tinygo
|
||||
// +build amd64 386 arm ppc64le wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchExp2 = true
|
||||
|
||||
func archExp2(x float32) float32
|
14
vendor/github.com/chewxy/math32/exp2_noasm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/exp2_noasm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build noasm || tinygo || !(amd64 || 386 || arm || ppc64le || wasm)
|
||||
// +build noasm tinygo !amd64,!386,!arm,!ppc64le,!wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchExp2 = false
|
||||
|
||||
func archExp2(x float32) float32 {
|
||||
panic("not implemented")
|
||||
}
|
114
vendor/github.com/chewxy/math32/exp_amd64.s
generated
vendored
Normal file
114
vendor/github.com/chewxy/math32/exp_amd64.s
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
//go:build !tinygo && !noasm
|
||||
// Copyright 2014 Xuanyi Chew. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// The original code is lifted from the Go standard library which is governed by
|
||||
// a BSD-style licence which can be found here: https://golang.org/LICENSE
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// The method is based on a paper by Naoki Shibata: "Efficient evaluation
|
||||
// methods of elementary functions suitable for SIMD computation", Proc.
|
||||
// of International Supercomputing Conference 2010 (ISC'10), pp. 25 -- 32
|
||||
// (May 2010). The paper is available at
|
||||
// http://www.springerlink.com/content/340228x165742104/
|
||||
//
|
||||
// The original code and the constants below are from the author's
|
||||
// implementation available at http://freshmeat.net/projects/sleef.
|
||||
// The README file says, "The software is in public domain.
|
||||
// You can use the software without any obligation."
|
||||
//
|
||||
// This code is a simplified version of the original.
|
||||
// The magic numbers for the float32 are lifted from the same project
|
||||
|
||||
|
||||
#define LN2 0.693147182464599609375 // log_e(2)
|
||||
#define LOG2E 1.44269502162933349609375 // 1/LN2
|
||||
#define LN2U 0.693145751953125 // upper half LN2
|
||||
#define LN2L 1.428606765330187045e-06 // lower half LN2
|
||||
#define T0 1.0
|
||||
#define T1 0.5
|
||||
#define T2 0.166665524244308471679688
|
||||
#define T3 0.0416710823774337768554688
|
||||
#define T4 0.00836596917361021041870117
|
||||
#define PosInf 0x7F800000
|
||||
#define NegInf 0xFF800000
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
// test bits for not-finite
|
||||
MOVL x+0(FP), BX
|
||||
MOVQ $~(1<<31), AX // sign bit mask
|
||||
MOVL BX, DX
|
||||
ANDL AX, DX
|
||||
MOVL $PosInf, AX
|
||||
CMPL AX, DX
|
||||
JLE notFinite
|
||||
MOVL BX, X0
|
||||
MOVSS $LOG2E, X1
|
||||
MULSS X0, X1
|
||||
CVTSS2SL X1, BX // BX = exponent
|
||||
CVTSL2SS BX, X1
|
||||
MOVSS $LN2U, X2
|
||||
MULSS X1, X2
|
||||
SUBSS X2, X0
|
||||
MOVSS $LN2L, X2
|
||||
MULSS X1, X2
|
||||
SUBSS X2, X0
|
||||
// reduce argument
|
||||
MULSS $0.0625, X0
|
||||
// Taylor series evaluation
|
||||
ADDSS $T4, X1
|
||||
MULSS X0, X1
|
||||
ADDSS $T3, X1
|
||||
MULSS X0, X1
|
||||
ADDSS $T2, X1
|
||||
MULSS X0, X1
|
||||
ADDSS $T1, X1
|
||||
MULSS X0, X1
|
||||
ADDSS $T0, X1
|
||||
MULSS X1, X0
|
||||
MOVSS $2.0, X1
|
||||
ADDSS X0, X1
|
||||
MULSS X1, X0
|
||||
MOVSS $2.0, X1
|
||||
ADDSS X0, X1
|
||||
MULSS X1, X0
|
||||
MOVSS $2.0, X1
|
||||
ADDSS X0, X1
|
||||
MULSS X1, X0
|
||||
MOVSS $2.0, X1
|
||||
ADDSS X0, X1
|
||||
MULSS X1, X0
|
||||
ADDSS $1.0, X0
|
||||
// return fr * 2**exponent
|
||||
MOVL $0x7F, AX // bias
|
||||
ADDL AX, BX
|
||||
JLE underflow
|
||||
CMPL BX, $0xFF
|
||||
JGE overflow
|
||||
MOVL $23, CX
|
||||
SHLQ CX, BX
|
||||
MOVL BX, X1
|
||||
MULSS X1, X0
|
||||
MOVSS X0, ret+8(FP)
|
||||
RET
|
||||
notFinite:
|
||||
// test bits for -Inf
|
||||
MOVL $NegInf, AX
|
||||
CMPQ AX, BX
|
||||
JNE notNegInf
|
||||
// -Inf, return 0
|
||||
underflow: // return 0
|
||||
MOVL $0, AX
|
||||
MOVL AX, ret+8(FP)
|
||||
RET
|
||||
overflow: // return +Inf
|
||||
MOVL $PosInf, BX
|
||||
notNegInf: // NaN or +Inf, return x
|
||||
MOVL BX, ret+8(FP)
|
||||
RET
|
||||
|
||||
TEXT ·archExp2(SB),NOSPLIT,$0
|
||||
JMP ·exp2(SB)
|
14
vendor/github.com/chewxy/math32/exp_asm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/exp_asm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !noasm && !tinygo && (amd64 || 386 || arm || ppc64le || wasm || s390x)
|
||||
// +build !noasm
|
||||
// +build !tinygo
|
||||
// +build amd64 386 arm ppc64le wasm s390x
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchExp = true
|
||||
|
||||
func archExp(x float32) float32
|
14
vendor/github.com/chewxy/math32/exp_noasm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/exp_noasm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build noasm || tinygo || !(amd64 || 386 || arm || ppc64le || wasm || s390x)
|
||||
// +build noasm tinygo !amd64,!386,!arm,!ppc64le,!wasm,!s390x
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchExp = false
|
||||
|
||||
func archExp(x float32) float32 {
|
||||
panic("not implemented")
|
||||
}
|
240
vendor/github.com/chewxy/math32/expm1f.go
generated
vendored
Normal file
240
vendor/github.com/chewxy/math32/expm1f.go
generated
vendored
Normal file
@ -0,0 +1,240 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package math32
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below are from FreeBSD's /usr/src/lib/msun/src/s_expm1.c
|
||||
// and came with this notice. The go code is a simplified
|
||||
// version of the original C.
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
// expm1(x)
|
||||
// Returns exp(x)-1, the exponential of x minus 1.
|
||||
//
|
||||
// Method
|
||||
// 1. Argument reduction:
|
||||
// Given x, find r and integer k such that
|
||||
//
|
||||
// x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
|
||||
//
|
||||
// Here a correction term c will be computed to compensate
|
||||
// the error in r when rounded to a floating-point number.
|
||||
//
|
||||
// 2. Approximating expm1(r) by a special rational function on
|
||||
// the interval [0,0.34658]:
|
||||
// Since
|
||||
// r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 - r**4/360 + ...
|
||||
// we define R1(r*r) by
|
||||
// r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 * R1(r*r)
|
||||
// That is,
|
||||
// R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
|
||||
// = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
|
||||
// = 1 - r**2/60 + r**4/2520 - r**6/100800 + ...
|
||||
// We use a special Reme algorithm on [0,0.347] to generate
|
||||
// a polynomial of degree 5 in r*r to approximate R1. The
|
||||
// maximum error of this polynomial approximation is bounded
|
||||
// by 2**-61. In other words,
|
||||
// R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
|
||||
// where Q1 = -1.6666666666666567384E-2,
|
||||
// Q2 = 3.9682539681370365873E-4,
|
||||
// Q3 = -9.9206344733435987357E-6,
|
||||
// Q4 = 2.5051361420808517002E-7,
|
||||
// Q5 = -6.2843505682382617102E-9;
|
||||
// (where z=r*r, and the values of Q1 to Q5 are listed below)
|
||||
// with error bounded by
|
||||
// | 5 | -61
|
||||
// | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
|
||||
// | |
|
||||
//
|
||||
// expm1(r) = exp(r)-1 is then computed by the following
|
||||
// specific way which minimize the accumulation rounding error:
|
||||
// 2 3
|
||||
// r r [ 3 - (R1 + R1*r/2) ]
|
||||
// expm1(r) = r + --- + --- * [--------------------]
|
||||
// 2 2 [ 6 - r*(3 - R1*r/2) ]
|
||||
//
|
||||
// To compensate the error in the argument reduction, we use
|
||||
// expm1(r+c) = expm1(r) + c + expm1(r)*c
|
||||
// ~ expm1(r) + c + r*c
|
||||
// Thus c+r*c will be added in as the correction terms for
|
||||
// expm1(r+c). Now rearrange the term to avoid optimization
|
||||
// screw up:
|
||||
// ( 2 2 )
|
||||
// ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
|
||||
// expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
|
||||
// ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
|
||||
// ( )
|
||||
//
|
||||
// = r - E
|
||||
// 3. Scale back to obtain expm1(x):
|
||||
// From step 1, we have
|
||||
// expm1(x) = either 2**k*[expm1(r)+1] - 1
|
||||
// = or 2**k*[expm1(r) + (1-2**-k)]
|
||||
// 4. Implementation notes:
|
||||
// (A). To save one multiplication, we scale the coefficient Qi
|
||||
// to Qi*2**i, and replace z by (x**2)/2.
|
||||
// (B). To achieve maximum accuracy, we compute expm1(x) by
|
||||
// (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
|
||||
// (ii) if k=0, return r-E
|
||||
// (iii) if k=-1, return 0.5*(r-E)-0.5
|
||||
// (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
|
||||
// else return 1.0+2.0*(r-E);
|
||||
// (v) if (k<-2||k>56) return 2**k(1-(E-r)) - 1 (or exp(x)-1)
|
||||
// (vi) if k <= 20, return 2**k((1-2**-k)-(E-r)), else
|
||||
// (vii) return 2**k(1-((E+2**-k)-r))
|
||||
//
|
||||
// Special cases:
|
||||
// expm1(INF) is INF, expm1(NaN) is NaN;
|
||||
// expm1(-INF) is -1, and
|
||||
// for finite argument, only expm1(0)=0 is exact.
|
||||
//
|
||||
// Accuracy:
|
||||
// according to an error analysis, the error is always less than
|
||||
// 1 ulp (unit in the last place).
|
||||
//
|
||||
// Misc. info.
|
||||
// For IEEE double
|
||||
// if x > 7.09782712893383973096e+02 then expm1(x) overflow
|
||||
//
|
||||
// Constants:
|
||||
// The hexadecimal values are the intended ones for the following
|
||||
// constants. The decimal values may be used, provided that the
|
||||
// compiler will convert from decimal to binary accurately enough
|
||||
// to produce the hexadecimal values shown.
|
||||
//
|
||||
|
||||
// Expm1 returns e**x - 1, the base-e exponential of x minus 1.
|
||||
// It is more accurate than Exp(x) - 1 when x is near zero.
|
||||
//
|
||||
// Special cases are:
|
||||
// Expm1(+Inf) = +Inf
|
||||
// Expm1(-Inf) = -1
|
||||
// Expm1(NaN) = NaN
|
||||
// Very large values overflow to -1 or +Inf.
|
||||
func Expm1(x float32) float32 {
|
||||
return expm1(x)
|
||||
}
|
||||
|
||||
func expm1(x float32) float32 {
|
||||
const (
|
||||
Othreshold = 89.415985 // 0x42b2d4fc
|
||||
Ln2X27 = 1.871497344970703125e+01 // 0x4195b844
|
||||
Ln2HalfX3 = 1.0397207736968994140625 // 0x3F851592
|
||||
Ln2Half = 3.465735912322998046875e-01 // 0x3eb17218
|
||||
Ln2Hi = 6.9313812256e-01 // 0x3f317180
|
||||
Ln2Lo = 9.0580006145e-06 // 0x3717f7d1
|
||||
InvLn2 = 1.4426950216e+00 // 0x3fb8aa3b
|
||||
Tiny = 1.0 / (1 << 54) // 2**-54 = 0x3c90000000000000
|
||||
|
||||
/* scaled coefficients related to expm1 */
|
||||
Q1 = -3.3333335072e-02 /* 0xbd088889 */
|
||||
Q2 = 1.5873016091e-03 /* 0x3ad00d01 */
|
||||
Q3 = -7.9365076090e-05 /* 0xb8a670cd */
|
||||
Q4 = 4.0082177293e-06 /* 0x36867e54 */
|
||||
Q5 = -2.0109921195e-07 /* 0xb457edbb */
|
||||
)
|
||||
|
||||
// special cases
|
||||
switch {
|
||||
case IsInf(x, 1) || IsNaN(x):
|
||||
return x
|
||||
case IsInf(x, -1):
|
||||
return -1
|
||||
}
|
||||
|
||||
absx := x
|
||||
sign := false
|
||||
if x < 0 {
|
||||
absx = -absx
|
||||
sign = true
|
||||
}
|
||||
|
||||
// filter out huge argument
|
||||
if absx >= Ln2X27 { // if |x| >= 27 * ln2
|
||||
if sign {
|
||||
return -1 // x < -56*ln2, return -1
|
||||
}
|
||||
if absx >= Othreshold { // if |x| >= 89.415985...
|
||||
return Inf(1)
|
||||
}
|
||||
}
|
||||
|
||||
// argument reduction
|
||||
var c float32
|
||||
var k int
|
||||
if absx > Ln2Half { // if |x| > 0.5 * ln2
|
||||
var hi, lo float32
|
||||
if absx < Ln2HalfX3 { // and |x| < 1.5 * ln2
|
||||
if !sign {
|
||||
hi = x - Ln2Hi
|
||||
lo = Ln2Lo
|
||||
k = 1
|
||||
} else {
|
||||
hi = x + Ln2Hi
|
||||
lo = -Ln2Lo
|
||||
k = -1
|
||||
}
|
||||
} else {
|
||||
if !sign {
|
||||
k = int(InvLn2*x + 0.5)
|
||||
} else {
|
||||
k = int(InvLn2*x - 0.5)
|
||||
}
|
||||
t := float32(k)
|
||||
hi = x - t*Ln2Hi // t * Ln2Hi is exact here
|
||||
lo = t * Ln2Lo
|
||||
}
|
||||
x = hi - lo
|
||||
c = (hi - x) - lo
|
||||
} else if absx < Tiny { // when |x| < 2**-54, return x
|
||||
return x
|
||||
} else {
|
||||
k = 0
|
||||
}
|
||||
|
||||
// x is now in primary range
|
||||
hfx := 0.5 * x
|
||||
hxs := x * hfx
|
||||
r1 := 1 + hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))))
|
||||
t := 3 - r1*hfx
|
||||
e := hxs * ((r1 - t) / (6.0 - x*t))
|
||||
if k != 0 {
|
||||
e = (x*(e-c) - c)
|
||||
e -= hxs
|
||||
switch {
|
||||
case k == -1:
|
||||
return 0.5*(x-e) - 0.5
|
||||
case k == 1:
|
||||
if x < -0.25 {
|
||||
return -2 * (e - (x + 0.5))
|
||||
}
|
||||
return 1 + 2*(x-e)
|
||||
case k <= -2 || k > 56: // suffice to return exp(x)-1
|
||||
y := 1 - (e - x)
|
||||
y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent
|
||||
return y - 1
|
||||
}
|
||||
if k < 20 {
|
||||
t := Float32frombits(0x3f800000 - (0x1000000 >> uint(k))) // t=1-2**-k
|
||||
y := t - (e - x)
|
||||
y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent
|
||||
return y
|
||||
}
|
||||
t := Float32frombits(uint32(0x7f-k) << 23) // 2**-k
|
||||
y := x - (e + t)
|
||||
y += 1
|
||||
y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent
|
||||
return y
|
||||
}
|
||||
return x - (x*e - hxs) // c is 0
|
||||
}
|
58
vendor/github.com/chewxy/math32/floor.go
generated
vendored
Normal file
58
vendor/github.com/chewxy/math32/floor.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
package math32
|
||||
|
||||
// Floor returns the greatest integer value less than or equal to x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Floor(±0) = ±0
|
||||
// Floor(±Inf) = ±Inf
|
||||
// Floor(NaN) = NaN
|
||||
func Floor(x float32) float32 {
|
||||
return floor(x)
|
||||
}
|
||||
|
||||
func floor(x float32) float32 {
|
||||
if x == 0 || IsNaN(x) || IsInf(x, 0) {
|
||||
return x
|
||||
}
|
||||
if x < 0 {
|
||||
d, fract := Modf(-x)
|
||||
if fract != 0.0 {
|
||||
d = d + 1
|
||||
}
|
||||
return -d
|
||||
}
|
||||
d, _ := Modf(x)
|
||||
return d
|
||||
}
|
||||
|
||||
// Ceil returns the least integer value greater than or equal to x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Ceil(±0) = ±0
|
||||
// Ceil(±Inf) = ±Inf
|
||||
// Ceil(NaN) = NaN
|
||||
func Ceil(x float32) float32 {
|
||||
return ceil(x)
|
||||
}
|
||||
|
||||
func ceil(x float32) float32 {
|
||||
return -Floor(-x)
|
||||
}
|
||||
|
||||
// Trunc returns the integer value of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Trunc(±0) = ±0
|
||||
// Trunc(±Inf) = ±Inf
|
||||
// Trunc(NaN) = NaN
|
||||
func Trunc(x float32) float32 {
|
||||
return trunc(x)
|
||||
}
|
||||
|
||||
func trunc(x float32) float32 {
|
||||
if x == 0 || IsNaN(x) || IsInf(x, 0) {
|
||||
return x
|
||||
}
|
||||
d, _ := Modf(x)
|
||||
return d
|
||||
}
|
31
vendor/github.com/chewxy/math32/frexp.go
generated
vendored
Normal file
31
vendor/github.com/chewxy/math32/frexp.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
package math32
|
||||
|
||||
// Frexp breaks f into a normalized fraction
|
||||
// and an integral power of two.
|
||||
// It returns frac and exp satisfying f == frac × 2**exp,
|
||||
// with the absolute value of frac in the interval [½, 1).
|
||||
//
|
||||
// Special cases are:
|
||||
// Frexp(±0) = ±0, 0
|
||||
// Frexp(±Inf) = ±Inf, 0
|
||||
// Frexp(NaN) = NaN, 0
|
||||
func Frexp(f float32) (frac float32, exp int) {
|
||||
return frexp(f)
|
||||
}
|
||||
|
||||
func frexp(f float32) (frac float32, exp int) {
|
||||
// special cases
|
||||
switch {
|
||||
case f == 0:
|
||||
return f, 0 // correctly return -0
|
||||
case IsInf(f, 0) || IsNaN(f):
|
||||
return f, 0
|
||||
}
|
||||
f, exp = normalize(f)
|
||||
x := Float32bits(f)
|
||||
exp += int((x>>shift)&mask) - bias + 1
|
||||
x &^= mask << shift
|
||||
x |= (-1 + bias) << shift
|
||||
frac = Float32frombits(x)
|
||||
return
|
||||
}
|
7
vendor/github.com/chewxy/math32/gamma.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/gamma.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Gamma(x float32) float32 {
|
||||
return float32(math.Gamma(float64(x)))
|
||||
}
|
41
vendor/github.com/chewxy/math32/hypot.go
generated
vendored
Normal file
41
vendor/github.com/chewxy/math32/hypot.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package math32
|
||||
|
||||
/*
|
||||
Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
|
||||
*/
|
||||
|
||||
// Hypot returns Sqrt(p*p + q*q), taking care to avoid
|
||||
// unnecessary overflow and underflow.
|
||||
//
|
||||
// Special cases are:
|
||||
// Hypot(±Inf, q) = +Inf
|
||||
// Hypot(p, ±Inf) = +Inf
|
||||
// Hypot(NaN, q) = NaN
|
||||
// Hypot(p, NaN) = NaN
|
||||
func Hypot(p, q float32) float32 {
|
||||
return hypot(p, q)
|
||||
}
|
||||
|
||||
func hypot(p, q float32) float32 {
|
||||
// special cases
|
||||
switch {
|
||||
case IsInf(p, 0) || IsInf(q, 0):
|
||||
return Inf(1)
|
||||
case IsNaN(p) || IsNaN(q):
|
||||
return NaN()
|
||||
}
|
||||
if p < 0 {
|
||||
p = -p
|
||||
}
|
||||
if q < 0 {
|
||||
q = -q
|
||||
}
|
||||
if p < q {
|
||||
p, q = q, p
|
||||
}
|
||||
if p == 0 {
|
||||
return 0
|
||||
}
|
||||
q = q / p
|
||||
return p * Sqrt(1+q*q)
|
||||
}
|
7
vendor/github.com/chewxy/math32/j0.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/j0.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func J0(x float32) float32 {
|
||||
return float32(math.J0(float64(x)))
|
||||
}
|
7
vendor/github.com/chewxy/math32/j1.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/j1.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func J1(x float32) float32 {
|
||||
return float32(math.J1(float64(x)))
|
||||
}
|
11
vendor/github.com/chewxy/math32/jn.go
generated
vendored
Normal file
11
vendor/github.com/chewxy/math32/jn.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Jn(n int, x float32) float32 {
|
||||
return float32(math.Jn(n, float64(x)))
|
||||
}
|
||||
|
||||
func Yn(n int, x float32) float32 {
|
||||
return float32(math.Yn(n, float64(x)))
|
||||
}
|
43
vendor/github.com/chewxy/math32/ldexp.go
generated
vendored
Normal file
43
vendor/github.com/chewxy/math32/ldexp.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package math32
|
||||
|
||||
// Ldexp is the inverse of Frexp.
|
||||
// It returns frac × 2**exp.
|
||||
//
|
||||
// Special cases are:
|
||||
// Ldexp(±0, exp) = ±0
|
||||
// Ldexp(±Inf, exp) = ±Inf
|
||||
// Ldexp(NaN, exp) = NaN
|
||||
func Ldexp(frac float32, exp int) float32 {
|
||||
return ldexp(frac, exp)
|
||||
}
|
||||
|
||||
func ldexp(frac float32, exp int) float32 {
|
||||
// special cases
|
||||
switch {
|
||||
case frac == 0:
|
||||
return frac // correctly return -0
|
||||
case IsInf(frac, 0) || IsNaN(frac):
|
||||
return frac
|
||||
}
|
||||
frac, e := normalize(frac)
|
||||
exp += e
|
||||
x := Float32bits(frac)
|
||||
exp += int(x>>shift)&mask - bias
|
||||
if exp < -149 {
|
||||
return Copysign(0, frac) // underflow
|
||||
}
|
||||
if exp > 127 { // overflow
|
||||
if frac < 0 {
|
||||
return Inf(-1)
|
||||
}
|
||||
return Inf(1)
|
||||
}
|
||||
var m float32 = 1
|
||||
if exp < -(127 - 1) { // denormal
|
||||
exp += shift
|
||||
m = 1.0 / (1 << 23) // 1/(2**-23)
|
||||
}
|
||||
x &^= mask << shift
|
||||
x |= uint32(exp+bias) << shift
|
||||
return m * Float32frombits(x)
|
||||
}
|
8
vendor/github.com/chewxy/math32/lgamma.go
generated
vendored
Normal file
8
vendor/github.com/chewxy/math32/lgamma.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Lgamma(x float32) (lgamma float32, sign int) {
|
||||
lg, sign := math.Lgamma(float64(x))
|
||||
return float32(lg), sign
|
||||
}
|
124
vendor/github.com/chewxy/math32/log.go
generated
vendored
Normal file
124
vendor/github.com/chewxy/math32/log.go
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
package math32
|
||||
|
||||
/*
|
||||
Floating-point logarithm.
|
||||
*/
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below are from FreeBSD's /usr/src/lib/msun/src/e_log.c
|
||||
// and came with this notice. The go code is a simpler
|
||||
// version of the original C.
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
// __ieee754_log(x)
|
||||
// Return the logarithm of x
|
||||
//
|
||||
// Method :
|
||||
// 1. Argument Reduction: find k and f such that
|
||||
// x = 2**k * (1+f),
|
||||
// where sqrt(2)/2 < 1+f < sqrt(2) .
|
||||
//
|
||||
// 2. Approximation of log(1+f).
|
||||
// Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
|
||||
// = 2s + 2/3 s**3 + 2/5 s**5 + .....,
|
||||
// = 2s + s*R
|
||||
// We use a special Reme algorithm on [0,0.1716] to generate
|
||||
// a polynomial of degree 14 to approximate R. The maximum error
|
||||
// of this polynomial approximation is bounded by 2**-58.45. In
|
||||
// other words,
|
||||
// 2 4 6 8 10 12 14
|
||||
// R(z) ~ L1*s +L2*s +L3*s +L4*s +L5*s +L6*s +L7*s
|
||||
// (the values of L1 to L7 are listed in the program) and
|
||||
// | 2 14 | -58.45
|
||||
// | L1*s +...+L7*s - R(z) | <= 2
|
||||
// | |
|
||||
// Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
|
||||
// In order to guarantee error in log below 1ulp, we compute log by
|
||||
// log(1+f) = f - s*(f - R) (if f is not too large)
|
||||
// log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
|
||||
//
|
||||
// 3. Finally, log(x) = k*Ln2 + log(1+f).
|
||||
// = k*Ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*Ln2_lo)))
|
||||
// Here Ln2 is split into two floating point number:
|
||||
// Ln2_hi + Ln2_lo,
|
||||
// where n*Ln2_hi is always exact for |n| < 2000.
|
||||
//
|
||||
// Special cases:
|
||||
// log(x) is NaN with signal if x < 0 (including -INF) ;
|
||||
// log(+INF) is +INF; log(0) is -INF with signal;
|
||||
// log(NaN) is that NaN with no signal.
|
||||
//
|
||||
// Accuracy:
|
||||
// according to an error analysis, the error is always less than
|
||||
// 1 ulp (unit in the last place).
|
||||
//
|
||||
// Constants:
|
||||
// The hexadecimal values are the intended ones for the following
|
||||
// constants. The decimal values may be used, provided that the
|
||||
// compiler will convert from decimal to binary accurately enough
|
||||
// to produce the hexadecimal values shown.
|
||||
|
||||
// Log returns the natural logarithm of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Log(+Inf) = +Inf
|
||||
// Log(0) = -Inf
|
||||
// Log(x < 0) = NaN
|
||||
// Log(NaN) = NaN
|
||||
func Log(x float32) float32 {
|
||||
if haveArchLog {
|
||||
return archLog(x)
|
||||
}
|
||||
return log(x)
|
||||
}
|
||||
|
||||
func log(x float32) float32 {
|
||||
const (
|
||||
Ln2Hi = 6.9313812256e-01 /* 0x3f317180 */
|
||||
Ln2Lo = 9.0580006145e-06 /* 0x3717f7d1 */
|
||||
L1 = 6.6666668653e-01 /* 0x3f2aaaab */
|
||||
L2 = 4.0000000596e-01 /* 0x3ecccccd */
|
||||
L3 = 2.8571429849e-01 /* 0x3e924925 */
|
||||
L4 = 2.2222198546e-01 /* 0x3e638e29 */
|
||||
L5 = 1.8183572590e-01 /* 0x3e3a3325 */
|
||||
L6 = 1.5313838422e-01 /* 0x3e1cd04f */
|
||||
L7 = 1.4798198640e-01 /* 0x3e178897 */
|
||||
)
|
||||
|
||||
// special cases
|
||||
switch {
|
||||
case IsNaN(x) || IsInf(x, 1):
|
||||
return x
|
||||
case x < 0:
|
||||
return NaN()
|
||||
case x == 0:
|
||||
return Inf(-1)
|
||||
}
|
||||
|
||||
// reduce
|
||||
f1, ki := Frexp(x)
|
||||
if f1 < Sqrt2/2 {
|
||||
f1 *= 2
|
||||
ki--
|
||||
}
|
||||
f := f1 - 1
|
||||
k := float32(ki)
|
||||
|
||||
// compute
|
||||
s := f / (2 + f)
|
||||
s2 := s * s
|
||||
s4 := s2 * s2
|
||||
t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7)))
|
||||
t2 := s4 * (L2 + s4*(L4+s4*L6))
|
||||
R := t1 + t2
|
||||
hfsq := 0.5 * f * f
|
||||
return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f)
|
||||
}
|
7
vendor/github.com/chewxy/math32/log10.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/log10.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Log10(x float32) float32 {
|
||||
return float32(math.Log10(float64(x)))
|
||||
}
|
7
vendor/github.com/chewxy/math32/log1p.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/log1p.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Log1p(x float32) float32 {
|
||||
return float32(math.Log1p(float64(x)))
|
||||
}
|
7
vendor/github.com/chewxy/math32/log2.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/log2.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Log2(x float32) float32 {
|
||||
return float32(math.Log2(float64(x)))
|
||||
}
|
112
vendor/github.com/chewxy/math32/log_amd64.s
generated
vendored
Normal file
112
vendor/github.com/chewxy/math32/log_amd64.s
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
//go:build !tinygo && !noasm
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSS-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
#define HSqrt2 7.07106781186547524401e-01 // sqrt(2)/2
|
||||
#define Ln2Hi 6.9313812256e-01 // 0x3f317180
|
||||
#define Ln2Lo 9.0580006145e-06 // 0x3717f7d1
|
||||
#define L1 6.6666668653e-01 // 0x3f2aaaab
|
||||
#define L2 4.0000000596e-01 // 0x3ecccccd
|
||||
#define L3 2.8571429849e-01 // 0x3e924925
|
||||
#define L4 2.2222198546e-01 // 0x3e638e29
|
||||
#define L5 1.8183572590e-01 // 0x3e3a3325
|
||||
#define L6 1.5313838422e-01 // 0x3e1cd04f
|
||||
#define L7 1.4798198640e-01 // 0x3e178897
|
||||
#define NaN 0x7FE00000
|
||||
#define PosInf 0x7F800000
|
||||
#define NegInf 0xFF800000
|
||||
|
||||
// func archLog(x float64) float64
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
// test bits for special cases
|
||||
MOVL x+0(FP), BX
|
||||
MOVQ $~(1<<31), AX // sign bit mask
|
||||
ANDQ BX, AX
|
||||
JEQ isZero
|
||||
MOVL $0, AX
|
||||
CMPL AX, BX
|
||||
JGT isNegative
|
||||
MOVL $PosInf, AX
|
||||
CMPQ AX, BX
|
||||
JLE isInfOrNaN
|
||||
// f1, ki := math.Frexp(x); k := float64(ki)
|
||||
MOVL BX, X0
|
||||
MOVL $0x007FFFFF, AX
|
||||
MOVL AX, X2
|
||||
ANDPS X0, X2
|
||||
MOVSS $0.5, X0 // 0x3FE0000000000000
|
||||
ORPS X0, X2 // X2= f1
|
||||
SHRQ $23, BX
|
||||
ANDL $0xFF, BX
|
||||
SUBL $0x7E, BX
|
||||
CVTSL2SS BX, X1 // x1= k, x2= f1
|
||||
// if f1 < math.Sqrt2/2 { k -= 1; f1 *= 2 }
|
||||
MOVSS $HSqrt2, X0 // x0= 0.7071, x1= k, x2= f1
|
||||
CMPSS X2, X0, 5 // cmpnlt; x0= 0 or ^0, x1= k, x2 = f1
|
||||
MOVSS $1.0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 1
|
||||
ANDPS X0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1
|
||||
SUBSS X3, X1 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1
|
||||
MOVSS $1.0, X0 // x0= 1, x1= k, x2= f1, x3= 0 or 1
|
||||
ADDSS X0, X3 // x0= 1, x1= k, x2= f1, x3= 1 or 2
|
||||
MULSS X3, X2 // x0= 1, x1= k, x2= f1
|
||||
// f := f1 - 1
|
||||
SUBSS X0, X2 // x1= k, x2= f
|
||||
// s := f / (2 + f)
|
||||
MOVSS $2.0, X0
|
||||
ADDSS X2, X0
|
||||
MOVUPS X2, X3
|
||||
DIVSS X0, X3 // x1=k, x2= f, x3= s
|
||||
// s2 := s * s
|
||||
MOVUPS X3, X4 // x1= k, x2= f, x3= s
|
||||
MULSS X4, X4 // x1= k, x2= f, x3= s, x4= s2
|
||||
// s4 := s2 * s2
|
||||
MOVUPS X4, X5 // x1= k, x2= f, x3= s, x4= s2
|
||||
MULSS X5, X5 // x1= k, x2= f, x3= s, x4= s2, x5= s4
|
||||
// t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7)))
|
||||
MOVSS $L7, X6
|
||||
MULSS X5, X6
|
||||
ADDSS $L5, X6
|
||||
MULSS X5, X6
|
||||
ADDSS $L3, X6
|
||||
MULSS X5, X6
|
||||
ADDSS $L1, X6
|
||||
MULSS X6, X4 // x1= k, x2= f, x3= s, x4= t1, x5= s4
|
||||
// t2 := s4 * (L2 + s4*(L4+s4*L6))
|
||||
MOVSS $L6, X6
|
||||
MULSS X5, X6
|
||||
ADDSS $L4, X6
|
||||
MULSS X5, X6
|
||||
ADDSS $L2, X6
|
||||
MULSS X6, X5 // x1= k, x2= f, x3= s, x4= t1, x5= t2
|
||||
// R := t1 + t2
|
||||
ADDSS X5, X4 // x1= k, x2= f, x3= s, x4= R
|
||||
// hfsq := 0.5 * f * f
|
||||
MOVSS $0.5, X0
|
||||
MULSS X2, X0
|
||||
MULSS X2, X0 // x0= hfsq, x1= k, x2= f, x3= s, x4= R
|
||||
// return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f)
|
||||
ADDSS X0, X4 // x0= hfsq, x1= k, x2= f, x3= s, x4= hfsq+R
|
||||
MULSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)
|
||||
MOVSS $Ln2Lo, X4
|
||||
MULSS X1, X4 // x4= k*Ln2Lo
|
||||
ADDSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)+k*Ln2Lo
|
||||
SUBSS X3, X0 // x0= hfsq-(s*(hfsq+R)+k*Ln2Lo), x1= k, x2= f
|
||||
SUBSS X2, X0 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k
|
||||
MULSS $Ln2Hi, X1 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k*Ln2Hi
|
||||
SUBSS X0, X1 // x1= k*Ln2Hi-((hfsq-(s*(hfsq+R)+k*Ln2Lo))-f)
|
||||
MOVSS X1, ret+8(FP)
|
||||
RET
|
||||
isInfOrNaN:
|
||||
MOVL BX, ret+8(FP) // +Inf or NaN, return x
|
||||
RET
|
||||
isNegative:
|
||||
MOVL $NaN, AX
|
||||
MOVL AX, ret+8(FP) // return NaN
|
||||
RET
|
||||
isZero:
|
||||
MOVL $NegInf, AX
|
||||
MOVL AX, ret+8(FP) // return -Inf
|
||||
RET
|
14
vendor/github.com/chewxy/math32/log_asm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/log_asm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !noasm && !tinygo && (amd64 || arm || s390x || 386 || arm64 || ppc64le || wasm)
|
||||
// +build !noasm
|
||||
// +build !tinygo
|
||||
// +build amd64 arm s390x 386 arm64 ppc64le wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchLog = true
|
||||
|
||||
func archLog(x float32) float32
|
14
vendor/github.com/chewxy/math32/log_noasm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/log_noasm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build noasm || tinygo || (!amd64 && !arm && !s390x && !386 && !arm64 && !ppc64le && !wasm)
|
||||
// +build noasm tinygo !amd64,!arm,!s390x,!386,!arm64,!ppc64le,!wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchLog = false
|
||||
|
||||
func archLog(x float32) float32 {
|
||||
panic("not implemented")
|
||||
}
|
11
vendor/github.com/chewxy/math32/logb.go
generated
vendored
Normal file
11
vendor/github.com/chewxy/math32/logb.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Logb(x float32) float32 {
|
||||
return float32(math.Logb(float64(x)))
|
||||
}
|
||||
|
||||
func Ilogb(x float32) int {
|
||||
return math.Ilogb(float64(x))
|
||||
}
|
44
vendor/github.com/chewxy/math32/mod.go
generated
vendored
Normal file
44
vendor/github.com/chewxy/math32/mod.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
package math32
|
||||
|
||||
// Mod returns the floating-point remainder of x/y.
|
||||
// The magnitude of the result is less than y and its
|
||||
// sign agrees with that of x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Mod(±Inf, y) = NaN
|
||||
// Mod(NaN, y) = NaN
|
||||
// Mod(x, 0) = NaN
|
||||
// Mod(x, ±Inf) = x
|
||||
// Mod(x, NaN) = NaN
|
||||
func Mod(x, y float32) float32 {
|
||||
return mod(x, y)
|
||||
}
|
||||
|
||||
func mod(x, y float32) float32 {
|
||||
if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) {
|
||||
return NaN()
|
||||
}
|
||||
if y < 0 {
|
||||
y = -y
|
||||
}
|
||||
|
||||
yfr, yexp := Frexp(y)
|
||||
sign := false
|
||||
r := x
|
||||
if x < 0 {
|
||||
r = -x
|
||||
sign = true
|
||||
}
|
||||
|
||||
for r >= y {
|
||||
rfr, rexp := Frexp(r)
|
||||
if rfr < yfr {
|
||||
rexp = rexp - 1
|
||||
}
|
||||
r = r - Ldexp(y, rexp-yexp)
|
||||
}
|
||||
if sign {
|
||||
r = -r
|
||||
}
|
||||
return r
|
||||
}
|
35
vendor/github.com/chewxy/math32/modf.go
generated
vendored
Normal file
35
vendor/github.com/chewxy/math32/modf.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package math32
|
||||
|
||||
// Modf returns integer and fractional floating-point numbers
|
||||
// that sum to f. Both values have the same sign as f.
|
||||
//
|
||||
// Special cases are:
|
||||
// Modf(±Inf) = ±Inf, NaN
|
||||
// Modf(NaN) = NaN, NaN
|
||||
func Modf(f float32) (int float32, frac float32) {
|
||||
return modf(f)
|
||||
}
|
||||
|
||||
func modf(f float32) (int float32, frac float32) {
|
||||
if f < 1 {
|
||||
switch {
|
||||
case f < 0:
|
||||
int, frac = Modf(-f)
|
||||
return -int, -frac
|
||||
case f == 0:
|
||||
return f, f // Return -0, -0 when f == -0
|
||||
}
|
||||
return 0, f
|
||||
}
|
||||
|
||||
x := Float32bits(f)
|
||||
e := uint(x>>shift)&mask - bias
|
||||
|
||||
// Keep the top 9+e bits, the integer part; clear the rest.
|
||||
if e < 32-9 {
|
||||
x &^= 1<<(32-9-e) - 1
|
||||
}
|
||||
int = Float32frombits(x)
|
||||
frac = f - int
|
||||
return
|
||||
}
|
28
vendor/github.com/chewxy/math32/nextafter.go
generated
vendored
Normal file
28
vendor/github.com/chewxy/math32/nextafter.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package math32
|
||||
|
||||
// Nextafter returns the next representable float32 value after x towards y.
|
||||
//
|
||||
// Special cases are:
|
||||
//
|
||||
// Nextafter32(x, x) = x
|
||||
// Nextafter32(NaN, y) = NaN
|
||||
// Nextafter32(x, NaN) = NaN
|
||||
func Nextafter(x, y float32) (r float32) {
|
||||
switch {
|
||||
case IsNaN(x) || IsNaN(y): // special case
|
||||
r = float32(NaN())
|
||||
case x == y:
|
||||
r = x
|
||||
case x == 0:
|
||||
r = float32(Copysign(Float32frombits(1), y))
|
||||
case (y > x) == (x > 0):
|
||||
r = Float32frombits(Float32bits(x) + 1)
|
||||
default:
|
||||
r = Float32frombits(Float32bits(x) - 1)
|
||||
}
|
||||
return
|
||||
}
|
139
vendor/github.com/chewxy/math32/pow.go
generated
vendored
Normal file
139
vendor/github.com/chewxy/math32/pow.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func isOddInt(x float32) bool {
|
||||
xi, xf := Modf(x)
|
||||
return xf == 0 && int32(xi)&1 == 1
|
||||
}
|
||||
|
||||
// Special cases taken from FreeBSD's /usr/src/lib/msun/src/e_pow.c
|
||||
// updated by IEEE Std. 754-2008 "Section 9.2.1 Special values".
|
||||
|
||||
// Pow returns x**y, the base-x exponential of y.
|
||||
//
|
||||
// Special cases are (in order):
|
||||
// Pow(x, ±0) = 1 for any x
|
||||
// Pow(1, y) = 1 for any y
|
||||
// Pow(x, 1) = x for any x
|
||||
// Pow(NaN, y) = NaN
|
||||
// Pow(x, NaN) = NaN
|
||||
// Pow(±0, y) = ±Inf for y an odd integer < 0
|
||||
// Pow(±0, -Inf) = +Inf
|
||||
// Pow(±0, +Inf) = +0
|
||||
// Pow(±0, y) = +Inf for finite y < 0 and not an odd integer
|
||||
// Pow(±0, y) = ±0 for y an odd integer > 0
|
||||
// Pow(±0, y) = +0 for finite y > 0 and not an odd integer
|
||||
// Pow(-1, ±Inf) = 1
|
||||
// Pow(x, +Inf) = +Inf for |x| > 1
|
||||
// Pow(x, -Inf) = +0 for |x| > 1
|
||||
// Pow(x, +Inf) = +0 for |x| < 1
|
||||
// Pow(x, -Inf) = +Inf for |x| < 1
|
||||
// Pow(+Inf, y) = +Inf for y > 0
|
||||
// Pow(+Inf, y) = +0 for y < 0
|
||||
// Pow(-Inf, y) = Pow(-0, -y)
|
||||
// Pow(x, y) = NaN for finite x < 0 and finite non-integer y
|
||||
func Pow(x, y float32) float32 {
|
||||
switch {
|
||||
case y == 0 || x == 1:
|
||||
return 1
|
||||
case y == 1:
|
||||
return x
|
||||
case y == 0.5:
|
||||
return Sqrt(x)
|
||||
case y == -0.5:
|
||||
return 1 / Sqrt(x)
|
||||
case IsNaN(x) || IsNaN(y):
|
||||
return NaN()
|
||||
case x == 0:
|
||||
switch {
|
||||
case y < 0:
|
||||
if isOddInt(y) {
|
||||
return Copysign(Inf(1), x)
|
||||
}
|
||||
return Inf(1)
|
||||
case y > 0:
|
||||
if isOddInt(y) {
|
||||
return x
|
||||
}
|
||||
return 0
|
||||
}
|
||||
case IsInf(y, 0):
|
||||
switch {
|
||||
case x == -1:
|
||||
return 1
|
||||
case (Abs(x) < 1) == IsInf(y, 1):
|
||||
return 0
|
||||
default:
|
||||
return Inf(1)
|
||||
}
|
||||
case IsInf(x, 0):
|
||||
if IsInf(x, -1) {
|
||||
return Pow(1/x, -y) // Pow(-0, -y)
|
||||
}
|
||||
switch {
|
||||
case y < 0:
|
||||
return 0
|
||||
case y > 0:
|
||||
return Inf(1)
|
||||
}
|
||||
}
|
||||
|
||||
absy := y
|
||||
flip := false
|
||||
if absy < 0 {
|
||||
absy = -absy
|
||||
flip = true
|
||||
}
|
||||
yi, yf := Modf(absy)
|
||||
if yf != 0 && x < 0 {
|
||||
return NaN()
|
||||
}
|
||||
if yi >= 1<<31 {
|
||||
return Exp(y * Log(x))
|
||||
}
|
||||
|
||||
// ans = a1 * 2**ae (= 1 for now).
|
||||
a1 := float32(1.0)
|
||||
ae := 0
|
||||
|
||||
// ans *= x**yf
|
||||
if yf != 0 {
|
||||
if yf > 0.5 {
|
||||
yf--
|
||||
yi++
|
||||
}
|
||||
a1 = Exp(yf * Log(x))
|
||||
}
|
||||
|
||||
// ans *= x**yi
|
||||
// by multiplying in successive squarings
|
||||
// of x according to bits of yi.
|
||||
// accumulate powers of two into exp.
|
||||
x1, xe := Frexp(x)
|
||||
for i := int32(yi); i != 0; i >>= 1 {
|
||||
if i&1 == 1 {
|
||||
a1 *= x1
|
||||
ae += xe
|
||||
}
|
||||
x1 *= x1
|
||||
xe <<= 1
|
||||
if x1 < .5 {
|
||||
x1 += x1
|
||||
xe--
|
||||
}
|
||||
}
|
||||
|
||||
// ans = a1*2**ae
|
||||
// if flip { ans = 1 / ans }
|
||||
// but in the opposite order
|
||||
if flip {
|
||||
a1 = 1 / a1
|
||||
ae = -ae
|
||||
}
|
||||
return Ldexp(a1, ae)
|
||||
}
|
||||
|
||||
func Pow10(e int) float32 {
|
||||
return float32(math.Pow10(e))
|
||||
}
|
95
vendor/github.com/chewxy/math32/remainder.go
generated
vendored
Normal file
95
vendor/github.com/chewxy/math32/remainder.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
package math32
|
||||
|
||||
// The original C code and the comment below are from
|
||||
// FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came
|
||||
// with this notice. The go code is a simplified version of
|
||||
// the original C.
|
||||
//
|
||||
// ====================================================
|
||||
// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
//
|
||||
// Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
// Permission to use, copy, modify, and distribute this
|
||||
// software is freely granted, provided that this notice
|
||||
// is preserved.
|
||||
// ====================================================
|
||||
//
|
||||
// __ieee754_remainder(x,y)
|
||||
// Return :
|
||||
// returns x REM y = x - [x/y]*y as if in infinite
|
||||
// precision arithmetic, where [x/y] is the (infinite bit)
|
||||
// integer nearest x/y (in half way cases, choose the even one).
|
||||
// Method :
|
||||
// Based on Mod() returning x - [x/y]chopped * y exactly.
|
||||
|
||||
// Remainder returns the IEEE 754 floating-point remainder of x/y.
|
||||
//
|
||||
// Special cases are:
|
||||
// Remainder(±Inf, y) = NaN
|
||||
// Remainder(NaN, y) = NaN
|
||||
// Remainder(x, 0) = NaN
|
||||
// Remainder(x, ±Inf) = x
|
||||
// Remainder(x, NaN) = NaN
|
||||
func Remainder(x, y float32) float32 {
|
||||
if haveArchRemainder {
|
||||
return archRemainder(x, y)
|
||||
}
|
||||
return remainder(x, y)
|
||||
}
|
||||
|
||||
func remainder(x, y float32) float32 {
|
||||
|
||||
// special cases
|
||||
switch {
|
||||
case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0:
|
||||
return NaN()
|
||||
case IsInf(y, 0):
|
||||
return x
|
||||
}
|
||||
|
||||
hx := Float32bits(x)
|
||||
hy := Float32bits(y)
|
||||
|
||||
hy &= 0x7fffffff
|
||||
hx &= 0x7fffffff
|
||||
|
||||
if hy <= 0x7effffff {
|
||||
x = Mod(x, y+y) // now x < 2y
|
||||
}
|
||||
|
||||
if hx-hy == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
|
||||
if y < 0 {
|
||||
y = -y
|
||||
}
|
||||
|
||||
if hy < 0x01000000 {
|
||||
if x+x > y {
|
||||
x -= y
|
||||
if x+x >= y {
|
||||
x -= y
|
||||
}
|
||||
}
|
||||
} else {
|
||||
yHalf := 0.5 * y
|
||||
if x > yHalf {
|
||||
x -= y
|
||||
if x >= yHalf {
|
||||
x -= y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sign {
|
||||
x = -x
|
||||
}
|
||||
return x
|
||||
}
|
9
vendor/github.com/chewxy/math32/remainder_amd64.s
generated
vendored
Normal file
9
vendor/github.com/chewxy/math32/remainder_amd64.s
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
//go:build !tinygo && !noasm
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
JMP ·remainder(SB)
|
10
vendor/github.com/chewxy/math32/remainder_asm.go
generated
vendored
Normal file
10
vendor/github.com/chewxy/math32/remainder_asm.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
//go:build !noasm && !tinygo && (amd64 || s390x || arm || ppc64le || 386 || wasm)
|
||||
// +build !noasm
|
||||
// +build !tinygo
|
||||
// +build amd64 s390x arm ppc64le 386 wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchRemainder = true
|
||||
|
||||
func archRemainder(x, y float32) float32
|
10
vendor/github.com/chewxy/math32/remainder_noasm.go
generated
vendored
Normal file
10
vendor/github.com/chewxy/math32/remainder_noasm.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
//go:build noasm || tinygo || (!amd64 && !s390x && !arm && !ppc64le && !386 && !wasm)
|
||||
// +build noasm tinygo !amd64,!s390x,!arm,!ppc64le,!386,!wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchRemainder = false
|
||||
|
||||
func archRemainder(x, y float32) float32 {
|
||||
panic("not implemented")
|
||||
}
|
76
vendor/github.com/chewxy/math32/round.go
generated
vendored
Normal file
76
vendor/github.com/chewxy/math32/round.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
package math32
|
||||
|
||||
// Round returns the nearest integer, rounding half away from zero.
|
||||
//
|
||||
// Special cases are:
|
||||
// Round(±0) = ±0
|
||||
// Round(±Inf) = ±Inf
|
||||
// Round(NaN) = NaN
|
||||
func Round(x float32) float32 {
|
||||
// Round is a faster implementation of:
|
||||
//
|
||||
// func Round(x float64) float64 {
|
||||
// t := Trunc(x)
|
||||
// if Abs(x-t) >= 0.5 {
|
||||
// return t + Copysign(1, x)
|
||||
// }
|
||||
// return t
|
||||
// }
|
||||
bits := Float32bits(x)
|
||||
e := uint(bits>>shift) & mask
|
||||
if e < bias {
|
||||
// Round abs(x) < 1 including denormals.
|
||||
bits &= signMask // +-0
|
||||
if e == bias-1 {
|
||||
bits |= uvone // +-1
|
||||
}
|
||||
} else if e < bias+shift {
|
||||
// Round any abs(x) >= 1 containing a fractional component [0,1).
|
||||
//
|
||||
// Numbers with larger exponents are returned unchanged since they
|
||||
// must be either an integer, infinity, or NaN.
|
||||
const half = 1 << (shift - 1)
|
||||
e -= bias
|
||||
bits += half >> e
|
||||
bits &^= fracMask >> e
|
||||
}
|
||||
return Float32frombits(bits)
|
||||
}
|
||||
|
||||
// RoundToEven returns the nearest integer, rounding ties to even.
|
||||
//
|
||||
// Special cases are:
|
||||
// RoundToEven(±0) = ±0
|
||||
// RoundToEven(±Inf) = ±Inf
|
||||
// RoundToEven(NaN) = NaN
|
||||
func RoundToEven(x float32) float32 {
|
||||
// RoundToEven is a faster implementation of:
|
||||
//
|
||||
// func RoundToEven(x float64) float64 {
|
||||
// t := math.Trunc(x)
|
||||
// odd := math.Remainder(t, 2) != 0
|
||||
// if d := math.Abs(x - t); d > 0.5 || (d == 0.5 && odd) {
|
||||
// return t + math.Copysign(1, x)
|
||||
// }
|
||||
// return t
|
||||
// }
|
||||
bits := Float32bits(x)
|
||||
e := uint(bits>>shift) & mask
|
||||
if e >= bias {
|
||||
// Round abs(x) >= 1.
|
||||
// - Large numbers without fractional components, infinity, and NaN are unchanged.
|
||||
// - Add 0.499.. or 0.5 before truncating depending on whether the truncated
|
||||
// number is even or odd (respectively).
|
||||
const halfMinusULP = (1 << (shift - 1)) - 1
|
||||
e -= bias
|
||||
bits += (halfMinusULP + (bits>>(shift-e))&1) >> e
|
||||
bits &^= fracMask >> e
|
||||
} else if e == bias-1 && bits&fracMask != 0 {
|
||||
// Round 0.5 < abs(x) < 1.
|
||||
bits = bits&signMask | uvone // +-1
|
||||
} else {
|
||||
// Round abs(x) <= 0.5 including denormals.
|
||||
bits &= signMask // +-0
|
||||
}
|
||||
return Float32frombits(bits)
|
||||
}
|
6
vendor/github.com/chewxy/math32/signbit.go
generated
vendored
Normal file
6
vendor/github.com/chewxy/math32/signbit.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
package math32
|
||||
|
||||
// Signbit returns true if x is negative or negative zero.
|
||||
func Signbit(x float32) bool {
|
||||
return Float32bits(x)&(1<<31) != 0
|
||||
}
|
387
vendor/github.com/chewxy/math32/sincos.go
generated
vendored
Normal file
387
vendor/github.com/chewxy/math32/sincos.go
generated
vendored
Normal file
@ -0,0 +1,387 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package math32
|
||||
|
||||
import "math/bits"
|
||||
|
||||
/*
|
||||
Floating-point sine and cosine.
|
||||
*/
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
|
||||
// available from http://www.netlib.org/cephes/cmath.tgz.
|
||||
// The go code is a simplified version of the original C.
|
||||
//
|
||||
// sin.c
|
||||
//
|
||||
// Circular sine
|
||||
//
|
||||
// SYNOPSIS:
|
||||
//
|
||||
// double x, y, sin();
|
||||
// y = sin( x );
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Range reduction is into intervals of pi/4. The reduction error is nearly
|
||||
// eliminated by contriving an extended precision modular arithmetic.
|
||||
//
|
||||
// Two polynomial approximating functions are employed.
|
||||
// Between 0 and pi/4 the sine is approximated by
|
||||
// x + x**3 P(x**2).
|
||||
// Between pi/4 and pi/2 the cosine is represented as
|
||||
// 1 - x**2 Q(x**2).
|
||||
//
|
||||
// ACCURACY:
|
||||
//
|
||||
// Relative error:
|
||||
// arithmetic domain # trials peak rms
|
||||
// DEC 0, 10 150000 3.0e-17 7.8e-18
|
||||
// IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
|
||||
//
|
||||
// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss
|
||||
// is not gradual, but jumps suddenly to about 1 part in 10e7. Results may
|
||||
// be meaningless for x > 2**49 = 5.6e14.
|
||||
//
|
||||
// cos.c
|
||||
//
|
||||
// Circular cosine
|
||||
//
|
||||
// SYNOPSIS:
|
||||
//
|
||||
// double x, y, cos();
|
||||
// y = cos( x );
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Range reduction is into intervals of pi/4. The reduction error is nearly
|
||||
// eliminated by contriving an extended precision modular arithmetic.
|
||||
//
|
||||
// Two polynomial approximating functions are employed.
|
||||
// Between 0 and pi/4 the cosine is approximated by
|
||||
// 1 - x**2 Q(x**2).
|
||||
// Between pi/4 and pi/2 the sine is represented as
|
||||
// x + x**3 P(x**2).
|
||||
//
|
||||
// ACCURACY:
|
||||
//
|
||||
// Relative error:
|
||||
// arithmetic domain # trials peak rms
|
||||
// IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17
|
||||
// DEC 0,+1.07e9 17000 3.0e-17 7.2e-18
|
||||
//
|
||||
// Cephes Math Library Release 2.8: June, 2000
|
||||
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
|
||||
//
|
||||
// The readme file at http://netlib.sandia.gov/cephes/ says:
|
||||
// Some software in this archive may be from the book _Methods and
|
||||
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
|
||||
// International, 1989) or from the Cephes Mathematical Library, a
|
||||
// commercial product. In either event, it is copyrighted by the author.
|
||||
// What you see here may be used freely but it comes with no support or
|
||||
// guarantee.
|
||||
//
|
||||
// The two known misprints in the book are repaired here in the
|
||||
// source listings for the gamma function and the incomplete beta
|
||||
// integral.
|
||||
//
|
||||
// Stephen L. Moshier
|
||||
// moshier@na-net.ornl.gov
|
||||
|
||||
// sin coefficients
|
||||
var _sin = [...]float32{
|
||||
1.58962301576546568060e-10, // 0x3de5d8fd1fd19ccd
|
||||
-2.50507477628578072866e-8, // 0xbe5ae5e5a9291f5d
|
||||
2.75573136213857245213e-6, // 0x3ec71de3567d48a1
|
||||
-1.98412698295895385996e-4, // 0xbf2a01a019bfdf03
|
||||
8.33333333332211858878e-3, // 0x3f8111111110f7d0
|
||||
-1.66666666666666307295e-1, // 0xbfc5555555555548
|
||||
}
|
||||
|
||||
// cos coefficients
|
||||
var _cos = [...]float32{
|
||||
-1.13585365213876817300e-11, // 0xbda8fa49a0861a9b
|
||||
2.08757008419747316778e-9, // 0x3e21ee9d7b4e3f05
|
||||
-2.75573141792967388112e-7, // 0xbe927e4f7eac4bc6
|
||||
2.48015872888517045348e-5, // 0x3efa01a019c844f5
|
||||
-1.38888888888730564116e-3, // 0xbf56c16c16c14f91
|
||||
4.16666666666665929218e-2, // 0x3fa555555555554b
|
||||
}
|
||||
|
||||
// Sincos returns Sin(x), Cos(x).
|
||||
//
|
||||
// Special cases are:
|
||||
// Sincos(±0) = ±0, 1
|
||||
// Sincos(±Inf) = NaN, NaN
|
||||
// Sincos(NaN) = NaN, NaN
|
||||
func Sincos(x float32) (sin, cos float32) {
|
||||
const (
|
||||
PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||
PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
|
||||
PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
|
||||
)
|
||||
// special cases
|
||||
switch {
|
||||
case x == 0:
|
||||
return x, 1 // return ±0.0, 1.0
|
||||
case IsNaN(x) || IsInf(x, 0):
|
||||
return NaN(), NaN()
|
||||
}
|
||||
|
||||
// make argument positive
|
||||
sinSign, cosSign := false, false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sinSign = true
|
||||
}
|
||||
|
||||
var j uint64
|
||||
var y, z float32
|
||||
if x >= reduceThreshold {
|
||||
j, z = trigReduce(x)
|
||||
} else {
|
||||
j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||
y = float32(j) // integer part of x/(Pi/4), as float
|
||||
|
||||
if j&1 == 1 { // map zeros to origin
|
||||
j++
|
||||
y++
|
||||
}
|
||||
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
||||
z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
|
||||
}
|
||||
if j > 3 { // reflect in x axis
|
||||
j -= 4
|
||||
sinSign, cosSign = !sinSign, !cosSign
|
||||
}
|
||||
if j > 1 {
|
||||
cosSign = !cosSign
|
||||
}
|
||||
|
||||
zz := z * z
|
||||
cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
|
||||
sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
|
||||
if j == 1 || j == 2 {
|
||||
sin, cos = cos, sin
|
||||
}
|
||||
if cosSign {
|
||||
cos = -cos
|
||||
}
|
||||
if sinSign {
|
||||
sin = -sin
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Sin returns the sine of the radian argument x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Sin(±0) = ±0
|
||||
// Sin(±Inf) = NaN
|
||||
// Sin(NaN) = NaN
|
||||
func Sin(x float32) float32 {
|
||||
const (
|
||||
PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||
PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
|
||||
PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
|
||||
)
|
||||
// special cases
|
||||
switch {
|
||||
case x == 0 || IsNaN(x):
|
||||
return x // return ±0 || NaN()
|
||||
case IsInf(x, 0):
|
||||
return NaN()
|
||||
}
|
||||
|
||||
// make argument positive but save the sign
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
|
||||
var j uint64
|
||||
var y, z float32
|
||||
if x >= reduceThreshold {
|
||||
j, z = trigReduce(x)
|
||||
} else {
|
||||
j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||
y = float32(j) // integer part of x/(Pi/4), as float
|
||||
|
||||
// map zeros to origin
|
||||
if j&1 == 1 {
|
||||
j++
|
||||
y++
|
||||
}
|
||||
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
||||
z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
|
||||
}
|
||||
// reflect in x axis
|
||||
if j > 3 {
|
||||
sign = !sign
|
||||
j -= 4
|
||||
}
|
||||
zz := z * z
|
||||
if j == 1 || j == 2 {
|
||||
y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
|
||||
} else {
|
||||
y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
|
||||
}
|
||||
if sign {
|
||||
y = -y
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// Cos returns the cosine of the radian argument x.
|
||||
//
|
||||
// Special cases are:
|
||||
// Cos(±Inf) = NaN
|
||||
// Cos(NaN) = NaN
|
||||
func Cos(x float32) float32 {
|
||||
const (
|
||||
PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||
PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
|
||||
PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
|
||||
)
|
||||
// special cases
|
||||
switch {
|
||||
case IsNaN(x) || IsInf(x, 0):
|
||||
return NaN()
|
||||
}
|
||||
|
||||
// make argument positive
|
||||
sign := false
|
||||
x = Abs(x)
|
||||
|
||||
var j uint64
|
||||
var y, z float32
|
||||
if x >= reduceThreshold {
|
||||
j, z = trigReduce(x)
|
||||
} else {
|
||||
j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||
y = float32(j) // integer part of x/(Pi/4), as float
|
||||
|
||||
// map zeros to origin
|
||||
if j&1 == 1 {
|
||||
j++
|
||||
y++
|
||||
}
|
||||
j &= 7 // octant modulo 2Pi radians (360 degrees)
|
||||
z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
|
||||
}
|
||||
|
||||
if j > 3 {
|
||||
j -= 4
|
||||
sign = !sign
|
||||
}
|
||||
if j > 1 {
|
||||
sign = !sign
|
||||
}
|
||||
|
||||
zz := z * z
|
||||
if j == 1 || j == 2 {
|
||||
y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
|
||||
} else {
|
||||
y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
|
||||
}
|
||||
if sign {
|
||||
y = -y
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// reduceThreshold is the maximum value of x where the reduction using Pi/4
|
||||
// in 3 float64 parts still gives accurate results. This threshold
|
||||
// is set by y*C being representable as a float64 without error
|
||||
// where y is given by y = floor(x * (4 / Pi)) and C is the leading partial
|
||||
// terms of 4/Pi. Since the leading terms (PI4A and PI4B in sin.go) have 30
|
||||
// and 32 trailing zero bits, y should have less than 30 significant bits.
|
||||
// y < 1<<30 -> floor(x*4/Pi) < 1<<30 -> x < (1<<30 - 1) * Pi/4
|
||||
// So, conservatively we can take x < 1<<29.
|
||||
// Above this threshold Payne-Hanek range reduction must be used.
|
||||
const reduceThreshold = 1 << 29
|
||||
|
||||
// trigReduce implements Payne-Hanek range reduction by Pi/4
|
||||
// for x > 0. It returns the integer part mod 8 (j) and
|
||||
// the fractional part (z) of x / (Pi/4).
|
||||
// The implementation is based on:
|
||||
// "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit"
|
||||
// K. C. Ng et al, March 24, 1992
|
||||
// The simulated multi-precision calculation of x*B uses 64-bit integer arithmetic.
|
||||
func trigReduce(x float32) (j uint64, z float32) {
|
||||
const PI4 = Pi / 4
|
||||
if x < PI4 {
|
||||
return 0, x
|
||||
}
|
||||
// Extract out the integer and exponent such that,
|
||||
// x = ix * 2 ** exp.
|
||||
ix := Float32bits(x)
|
||||
exp := int(ix>>shift&mask) - bias - shift
|
||||
ix &^= mask << shift
|
||||
ix |= 1 << shift
|
||||
// Use the exponent to extract the 3 appropriate uint64 digits from mPi4,
|
||||
// B ~ (z0, z1, z2), such that the product leading digit has the exponent -61.
|
||||
// Note, exp >= -53 since x >= PI4 and exp < 971 for maximum float64.
|
||||
const floatingbits = 32 - 3
|
||||
digit, bitshift := uint(exp+floatingbits)/32, uint(exp+floatingbits)%32
|
||||
z0 := (mPi4[digit] << bitshift) | (mPi4[digit+1] >> (32 - bitshift))
|
||||
z1 := (mPi4[digit+1] << bitshift) | (mPi4[digit+2] >> (32 - bitshift))
|
||||
z2 := (mPi4[digit+2] << bitshift) | (mPi4[digit+3] >> (32 - bitshift))
|
||||
// Multiply mantissa by the digits and extract the upper two digits (hi, lo).
|
||||
z2hi, _ := bits.Mul64(z2, uint64(ix))
|
||||
z1hi, z1lo := bits.Mul64(z1, uint64(ix))
|
||||
z0lo := z0 * uint64(ix)
|
||||
lo, c := bits.Add64(z1lo, z2hi, 0)
|
||||
hi, _ := bits.Add64(z0lo, z1hi, c)
|
||||
// The top 3 bits are j.
|
||||
j = hi >> floatingbits
|
||||
// Extract the fraction and find its magnitude.
|
||||
hi = hi<<3 | lo>>floatingbits
|
||||
lz := uint(bits.LeadingZeros64(hi))
|
||||
e := uint64(bias - (lz + 1))
|
||||
// Clear implicit mantissa bit and shift into place.
|
||||
hi = (hi << (lz + 1)) | (lo >> (32 - (lz + 1)))
|
||||
hi >>= 43 - shift
|
||||
// Include the exponent and convert to a float.
|
||||
hi |= e << shift
|
||||
z = Float32frombits(uint32(hi))
|
||||
// Map zeros to origin.
|
||||
if j&1 == 1 {
|
||||
j++
|
||||
j &= 7
|
||||
z--
|
||||
}
|
||||
// Multiply the fractional part by pi/4.
|
||||
return j, z * PI4
|
||||
}
|
||||
|
||||
// mPi4 is the binary digits of 4/pi as a uint64 array,
|
||||
// that is, 4/pi = Sum mPi4[i]*2^(-64*i)
|
||||
// 19 64-bit digits and the leading one bit give 1217 bits
|
||||
// of precision to handle the largest possible float64 exponent.
|
||||
var mPi4 = [...]uint64{
|
||||
0x0000000000000001,
|
||||
0x45f306dc9c882a53,
|
||||
0xf84eafa3ea69bb81,
|
||||
0xb6c52b3278872083,
|
||||
0xfca2c757bd778ac3,
|
||||
0x6e48dc74849ba5c0,
|
||||
0x0c925dd413a32439,
|
||||
0xfc3bd63962534e7d,
|
||||
0xd1046bea5d768909,
|
||||
0xd338e04d68befc82,
|
||||
0x7323ac7306a673e9,
|
||||
0x3908bf177bf25076,
|
||||
0x3ff12fffbc0b301f,
|
||||
0xde5e2316b414da3e,
|
||||
0xda6cfd9e4f96136e,
|
||||
0x9e8c7ecd3cbfd45a,
|
||||
0xea4f758fd7cbe2f6,
|
||||
0x7a0e73ef14a525d4,
|
||||
0xd7f6bf623f1aba10,
|
||||
0xac06608df8f6d757,
|
||||
}
|
40
vendor/github.com/chewxy/math32/sinhf.go
generated
vendored
Normal file
40
vendor/github.com/chewxy/math32/sinhf.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
package math32
|
||||
|
||||
func Sinh(x float32) float32 {
|
||||
// The coefficients are #2029 from Hart & Cheney. (20.36D)
|
||||
const (
|
||||
P0 = -0.6307673640497716991184787251e+6
|
||||
P1 = -0.8991272022039509355398013511e+5
|
||||
P2 = -0.2894211355989563807284660366e+4
|
||||
P3 = -0.2630563213397497062819489e+2
|
||||
Q0 = -0.6307673640497716991212077277e+6
|
||||
Q1 = 0.1521517378790019070696485176e+5
|
||||
Q2 = -0.173678953558233699533450911e+3
|
||||
)
|
||||
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
|
||||
var temp float32
|
||||
switch {
|
||||
case x > 21:
|
||||
temp = Exp(x) * 0.5
|
||||
|
||||
case x > 0.5:
|
||||
ex := Exp(x)
|
||||
temp = (ex - 1/ex) * 0.5
|
||||
|
||||
default:
|
||||
sq := x * x
|
||||
temp = (((P3*sq+P2)*sq+P1)*sq + P0) * x
|
||||
temp = temp / (((sq+Q2)*sq+Q1)*sq + Q0)
|
||||
}
|
||||
|
||||
if sign {
|
||||
temp = -temp
|
||||
}
|
||||
return temp
|
||||
}
|
65
vendor/github.com/chewxy/math32/sqrt.go
generated
vendored
Normal file
65
vendor/github.com/chewxy/math32/sqrt.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
package math32
|
||||
|
||||
// Sqrt returns the square root of x.
|
||||
|
||||
// Special cases are:
|
||||
// Sqrt(+Inf) = +Inf
|
||||
// Sqrt(±0) = ±0
|
||||
// Sqrt(x < 0) = NaN
|
||||
// Sqrt(NaN) = NaN
|
||||
func Sqrt(x float32) float32 {
|
||||
if haveArchSqrt {
|
||||
return archSqrt(x)
|
||||
}
|
||||
return sqrt(x)
|
||||
}
|
||||
|
||||
// TODO: add assembly for !build noasm
|
||||
func sqrt(x float32) float32 {
|
||||
// special cases
|
||||
switch {
|
||||
case x == 0 || IsNaN(x) || IsInf(x, 1):
|
||||
return x
|
||||
case x < 0:
|
||||
return NaN()
|
||||
}
|
||||
ix := Float32bits(x)
|
||||
|
||||
// normalize x
|
||||
exp := int((ix >> shift) & mask)
|
||||
if exp == 0 { // subnormal x
|
||||
for ix&(1<<shift) == 0 {
|
||||
ix <<= 1
|
||||
exp--
|
||||
}
|
||||
exp++
|
||||
}
|
||||
exp -= bias // unbias exponent
|
||||
ix &^= mask << shift
|
||||
ix |= 1 << shift
|
||||
if exp&1 == 1 { // odd exp, double x to make it even
|
||||
ix <<= 1
|
||||
}
|
||||
exp >>= 1 // exp = exp/2, exponent of square root
|
||||
// generate sqrt(x) bit by bit
|
||||
ix <<= 1
|
||||
var q, s uint32 // q = sqrt(x)
|
||||
r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB
|
||||
for r != 0 {
|
||||
t := s + r
|
||||
if t <= ix {
|
||||
s = t + r
|
||||
ix -= t
|
||||
q += r
|
||||
}
|
||||
ix <<= 1
|
||||
r >>= 1
|
||||
}
|
||||
// final rounding
|
||||
if ix != 0 { // remainder, result not exact
|
||||
q += q & 1 // round according to extra bit
|
||||
}
|
||||
ix = q>>1 + uint32(exp-1+bias)<<shift // significand + biased exponent
|
||||
return Float32frombits(ix)
|
||||
|
||||
}
|
9
vendor/github.com/chewxy/math32/sqrt_amd64.s
generated
vendored
Normal file
9
vendor/github.com/chewxy/math32/sqrt_amd64.s
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
MOVSS x+0(FP), X0
|
||||
SQRTSS X0, X0
|
||||
MOVSS X0, ret+8(FP)
|
||||
RET
|
13
vendor/github.com/chewxy/math32/sqrt_arm64.s
generated
vendored
Normal file
13
vendor/github.com/chewxy/math32/sqrt_arm64.s
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
//go:build !tinygo && !noasm
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
FMOVS x+0(FP), F0
|
||||
FSQRTS F0, F0
|
||||
FMOVS F0, ret+8(FP)
|
||||
RET
|
14
vendor/github.com/chewxy/math32/sqrt_asm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/sqrt_asm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !noasm && !tinygo && (386 || amd64 || arm64 || arm || ppc64le || s390x || wasm)
|
||||
// +build !noasm
|
||||
// +build !tinygo
|
||||
// +build 386 amd64 arm64 arm ppc64le s390x wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchSqrt = true
|
||||
|
||||
func archSqrt(x float32) float32
|
14
vendor/github.com/chewxy/math32/sqrt_noasm.go
generated
vendored
Normal file
14
vendor/github.com/chewxy/math32/sqrt_noasm.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build noasm || tinygo || (!386 && !amd64 && !arm64 && !arm && !ppc64le && !s390x && !wasm)
|
||||
// +build noasm tinygo !386,!amd64,!arm64,!arm,!ppc64le,!s390x,!wasm
|
||||
|
||||
package math32
|
||||
|
||||
const haveArchSqrt = false
|
||||
|
||||
func archSqrt(x float32) float32 {
|
||||
panic("not implemented")
|
||||
}
|
22
vendor/github.com/chewxy/math32/stubs_386.s
generated
vendored
Normal file
22
vendor/github.com/chewxy/math32/stubs_386.s
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
JMP ·exp(SB)
|
||||
|
||||
// func archExp2(x float32) float32
|
||||
TEXT ·archExp2(SB),NOSPLIT,$0
|
||||
JMP ·exp2(SB)
|
||||
|
||||
// func archLog(x float32) float32
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
JMP ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
JMP ·remainder(SB)
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
JMP ·sqrt(SB)
|
22
vendor/github.com/chewxy/math32/stubs_arm.s
generated
vendored
Normal file
22
vendor/github.com/chewxy/math32/stubs_arm.s
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
B ·exp(SB)
|
||||
|
||||
// func archExp2(x float32) float32
|
||||
TEXT ·archExp2(SB),NOSPLIT,$0
|
||||
B ·exp2(SB)
|
||||
|
||||
// func archLog(x float32) float32
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
B ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
B ·remainder(SB)
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
B ·sqrt(SB)
|
10
vendor/github.com/chewxy/math32/stubs_arm64.s
generated
vendored
Normal file
10
vendor/github.com/chewxy/math32/stubs_arm64.s
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archLog(x float64) float64
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
B ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32 // TODO
|
||||
// TEXT ·archRemainderTODO(SB),NOSPLIT,$0
|
||||
// B ·remainder(SB)
|
22
vendor/github.com/chewxy/math32/stubs_ppc64le.s
generated
vendored
Normal file
22
vendor/github.com/chewxy/math32/stubs_ppc64le.s
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
JMP ·exp(SB)
|
||||
|
||||
// func archExp2(x float32) float32
|
||||
TEXT ·archExp2(SB),NOSPLIT,$0
|
||||
JMP ·exp2(SB)
|
||||
|
||||
// func archLog(x float32) float32
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
JMP ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
JMP ·remainder(SB)
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
JMP ·sqrt(SB)
|
18
vendor/github.com/chewxy/math32/stubs_s390x.s
generated
vendored
Normal file
18
vendor/github.com/chewxy/math32/stubs_s390x.s
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
//go:build !tinygo && !noasm
|
||||
#include "textflag.h"
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
BR ·exp(SB)
|
||||
|
||||
// func archLog(x float32) float32
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
BR ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
BR ·remainder(SB)
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
BR ·sqrt(SB)
|
24
vendor/github.com/chewxy/math32/stubs_wasm.s
generated
vendored
Normal file
24
vendor/github.com/chewxy/math32/stubs_wasm.s
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
//go:build wasm && !tinygo && !noasm
|
||||
// +build wasm,!tinygo,!noasm
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func archExp(x float32) float32
|
||||
TEXT ·archExp(SB),NOSPLIT,$0
|
||||
JMP ·exp(SB)
|
||||
|
||||
// func archExp2(x float32) float32
|
||||
TEXT ·archExp2(SB),NOSPLIT,$0
|
||||
JMP ·exp2(SB)
|
||||
|
||||
// func archLog(x float32) float32
|
||||
TEXT ·archLog(SB),NOSPLIT,$0
|
||||
JMP ·log(SB)
|
||||
|
||||
// func archRemainder(x, y float32) float32
|
||||
TEXT ·archRemainder(SB),NOSPLIT,$0
|
||||
JMP ·remainder(SB)
|
||||
|
||||
// func archSqrt(x float32) float32
|
||||
TEXT ·archSqrt(SB),NOSPLIT,$0
|
||||
JMP ·sqrt(SB)
|
126
vendor/github.com/chewxy/math32/tan.go
generated
vendored
Normal file
126
vendor/github.com/chewxy/math32/tan.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
package math32
|
||||
|
||||
/*
|
||||
Floating-point tangent.
|
||||
*/
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
|
||||
// available from http://www.netlib.org/cephes/cmath.tgz.
|
||||
// The go code is a simplified version of the original C.
|
||||
//
|
||||
// tan.c
|
||||
//
|
||||
// Circular tangent
|
||||
//
|
||||
// SYNOPSIS:
|
||||
//
|
||||
// double x, y, tan();
|
||||
// y = tan( x );
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Returns the circular tangent of the radian argument x.
|
||||
//
|
||||
// Range reduction is modulo pi/4. A rational function
|
||||
// x + x**3 P(x**2)/Q(x**2)
|
||||
// is employed in the basic interval [0, pi/4].
|
||||
//
|
||||
// ACCURACY:
|
||||
// Relative error:
|
||||
// arithmetic domain # trials peak rms
|
||||
// DEC +-1.07e9 44000 4.1e-17 1.0e-17
|
||||
// IEEE +-1.07e9 30000 2.9e-16 8.1e-17
|
||||
//
|
||||
// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss
|
||||
// is not gradual, but jumps suddenly to about 1 part in 10e7. Results may
|
||||
// be meaningless for x > 2**49 = 5.6e14.
|
||||
// [Accuracy loss statement from sin.go comments.]
|
||||
//
|
||||
// Cephes Math Library Release 2.8: June, 2000
|
||||
// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
|
||||
//
|
||||
// The readme file at http://netlib.sandia.gov/cephes/ says:
|
||||
// Some software in this archive may be from the book _Methods and
|
||||
// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
|
||||
// International, 1989) or from the Cephes Mathematical Library, a
|
||||
// commercial product. In either event, it is copyrighted by the author.
|
||||
// What you see here may be used freely but it comes with no support or
|
||||
// guarantee.
|
||||
//
|
||||
// The two known misprints in the book are repaired here in the
|
||||
// source listings for the gamma function and the incomplete beta
|
||||
// integral.
|
||||
//
|
||||
// Stephen L. Moshier
|
||||
// moshier@na-net.ornl.gov
|
||||
|
||||
// tan coefficients
|
||||
var _tanP = [...]float32{
|
||||
-1.30936939181383777646e4, // 0xc0c992d8d24f3f38
|
||||
1.15351664838587416140e6, // 0x413199eca5fc9ddd
|
||||
-1.79565251976484877988e7, // 0xc1711fead3299176
|
||||
}
|
||||
var _tanQ = [...]float32{
|
||||
1.00000000000000000000e0,
|
||||
1.36812963470692954678e4, //0x40cab8a5eeb36572
|
||||
-1.32089234440210967447e6, //0xc13427bc582abc96
|
||||
2.50083801823357915839e7, //0x4177d98fc2ead8ef
|
||||
-5.38695755929454629881e7, //0xc189afe03cbe5a31
|
||||
}
|
||||
|
||||
func Tan(x float32) float32 {
|
||||
return tan(x)
|
||||
}
|
||||
|
||||
func tan(x float32) float32 {
|
||||
const (
|
||||
PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts
|
||||
PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000,
|
||||
PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170,
|
||||
)
|
||||
// special cases
|
||||
switch {
|
||||
case x == 0 || IsNaN(x):
|
||||
return x // return ±0 || NaN()
|
||||
case IsInf(x, 0):
|
||||
return NaN()
|
||||
}
|
||||
|
||||
// make argument positive but save the sign
|
||||
sign := false
|
||||
if x < 0 {
|
||||
x = -x
|
||||
sign = true
|
||||
}
|
||||
var j uint64
|
||||
var y, z float32
|
||||
if x >= reduceThreshold {
|
||||
j, z = trigReduce(x)
|
||||
} else {
|
||||
j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle
|
||||
y = float32(j) // integer part of x/(Pi/4), as float
|
||||
|
||||
/* map zeros and singularities to origin */
|
||||
if j&1 == 1 {
|
||||
j++
|
||||
y++
|
||||
}
|
||||
|
||||
z = ((x - y*PI4A) - y*PI4B) - y*PI4C
|
||||
}
|
||||
zz := z * z
|
||||
|
||||
if zz > 1e-14 {
|
||||
y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4]))
|
||||
} else {
|
||||
y = z
|
||||
}
|
||||
if j&2 == 2 {
|
||||
y = -1 / y
|
||||
}
|
||||
if sign {
|
||||
y = -y
|
||||
}
|
||||
return y
|
||||
}
|
77
vendor/github.com/chewxy/math32/tanh.go
generated
vendored
Normal file
77
vendor/github.com/chewxy/math32/tanh.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
package math32
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
// below were from http://netlib.sandia.gov/cephes/cmath/tanh.c,
|
||||
// available from http://www.netlib.org/cephes/single.tgz.
|
||||
// The go code is a simplified version of the original C.
|
||||
// tanhf.c
|
||||
//
|
||||
// Hyperbolic tangent
|
||||
//
|
||||
//
|
||||
//
|
||||
// SYNOPSIS:
|
||||
//
|
||||
// float x, y, tanhf();
|
||||
//
|
||||
// y = tanhf( x );
|
||||
//
|
||||
//
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Returns hyperbolic tangent of argument in the range MINLOG to
|
||||
// MAXLOG.
|
||||
//
|
||||
// A polynomial approximation is used for |x| < 0.625.
|
||||
// Otherwise,
|
||||
//
|
||||
// tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1).
|
||||
//
|
||||
//
|
||||
//
|
||||
// ACCURACY:
|
||||
//
|
||||
// Relative error:
|
||||
// arithmetic domain # trials peak rms
|
||||
// IEEE -2,2 100000 1.3e-7 2.6e-8
|
||||
//
|
||||
//
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.2: June, 1992
|
||||
Copyright 1984, 1987, 1989, 1992 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
/* Single precision hyperbolic tangent
|
||||
* test interval: [-0.625, +0.625]
|
||||
* trials: 10000
|
||||
* peak relative error: 7.2e-8
|
||||
* rms relative error: 2.6e-8
|
||||
*/
|
||||
|
||||
func Tanh(x float32) float32 {
|
||||
const MAXLOG = 88.02969187150841
|
||||
z := Abs(x)
|
||||
switch {
|
||||
case z > 0.5*MAXLOG:
|
||||
if x < 0 {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
case z >= 0.625:
|
||||
s := Exp(z + z)
|
||||
z = 1 - 2/(s+1)
|
||||
if x < 0 {
|
||||
z = -z
|
||||
}
|
||||
default:
|
||||
if x == 0 {
|
||||
return x
|
||||
}
|
||||
s := x * x
|
||||
z = ((((-5.70498872745E-3*s+2.06390887954E-2)*s-5.37397155531E-2)*s+1.33314422036E-1)*s-3.33332819422E-1)*s*x + x
|
||||
}
|
||||
return z
|
||||
}
|
21
vendor/github.com/chewxy/math32/unsafe.go
generated
vendored
Normal file
21
vendor/github.com/chewxy/math32/unsafe.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
package math32
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Float32bits returns the IEEE 754 binary representation of f.
|
||||
func Float32bits(f float32) uint32 { return *(*uint32)(unsafe.Pointer(&f)) }
|
||||
|
||||
// Float32frombits returns the floating point number corresponding
|
||||
// to the IEEE 754 binary representation b.
|
||||
func Float32frombits(b uint32) float32 { return *(*float32)(unsafe.Pointer(&b)) }
|
||||
|
||||
// Float64bits returns the IEEE 754 binary representation of f.
|
||||
func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
|
||||
|
||||
// Float64frombits returns the floating point number corresponding
|
||||
// the IEEE 754 binary representation b.
|
||||
func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) }
|
||||
|
||||
func float32ibits(f float32) int32 { return *(*int32)(unsafe.Pointer(&f)) }
|
||||
|
||||
func float32fromibits(b int32) float32 { return *(*float32)(unsafe.Pointer(&b)) }
|
7
vendor/github.com/chewxy/math32/y0.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/y0.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Y0(x float32) float32 {
|
||||
return float32(math.Y0(float64(x)))
|
||||
}
|
7
vendor/github.com/chewxy/math32/y1.go
generated
vendored
Normal file
7
vendor/github.com/chewxy/math32/y1.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package math32
|
||||
|
||||
import "math"
|
||||
|
||||
func Y1(x float32) float32 {
|
||||
return float32(math.Y1(float64(x)))
|
||||
}
|
27
vendor/github.com/ebitengine/gomobile/LICENSE
generated
vendored
Normal file
27
vendor/github.com/ebitengine/gomobile/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/github.com/ebitengine/gomobile/PATENTS
generated
vendored
Normal file
22
vendor/github.com/ebitengine/gomobile/PATENTS
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
67
vendor/github.com/ebitengine/gomobile/app/GoNativeActivity.java
generated
vendored
Normal file
67
vendor/github.com/ebitengine/gomobile/app/GoNativeActivity.java
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
package org.golang.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NativeActivity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.KeyCharacterMap;
|
||||
|
||||
public class GoNativeActivity extends NativeActivity {
|
||||
private static GoNativeActivity goNativeActivity;
|
||||
|
||||
public GoNativeActivity() {
|
||||
super();
|
||||
goNativeActivity = this;
|
||||
}
|
||||
|
||||
String getTmpdir() {
|
||||
return getCacheDir().getAbsolutePath();
|
||||
}
|
||||
|
||||
static int getRune(int deviceId, int keyCode, int metaState) {
|
||||
try {
|
||||
int rune = KeyCharacterMap.load(deviceId).get(keyCode, metaState);
|
||||
if (rune == 0) {
|
||||
return -1;
|
||||
}
|
||||
return rune;
|
||||
} catch (KeyCharacterMap.UnavailableException e) {
|
||||
return -1;
|
||||
} catch (Exception e) {
|
||||
Log.e("Go", "exception reading KeyCharacterMap", e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void load() {
|
||||
// Interestingly, NativeActivity uses a different method
|
||||
// to find native code to execute, avoiding
|
||||
// System.loadLibrary. The result is Java methods
|
||||
// implemented in C with JNIEXPORT (and JNI_OnLoad) are not
|
||||
// available unless an explicit call to System.loadLibrary
|
||||
// is done. So we do it here, borrowing the name of the
|
||||
// library from the same AndroidManifest.xml metadata used
|
||||
// by NativeActivity.
|
||||
try {
|
||||
ActivityInfo ai = getPackageManager().getActivityInfo(
|
||||
getIntent().getComponent(), PackageManager.GET_META_DATA);
|
||||
if (ai.metaData == null) {
|
||||
Log.e("Go", "loadLibrary: no manifest metadata found");
|
||||
return;
|
||||
}
|
||||
String libName = ai.metaData.getString("android.app.lib_name");
|
||||
System.loadLibrary(libName);
|
||||
} catch (Exception e) {
|
||||
Log.e("Go", "loadLibrary failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
load();
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
201
vendor/github.com/ebitengine/gomobile/app/android.c
generated
vendored
Normal file
201
vendor/github.com/ebitengine/gomobile/app/android.c
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build android
|
||||
// +build android
|
||||
|
||||
#include <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
#define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "Go", __VA_ARGS__)
|
||||
#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__)
|
||||
|
||||
static jclass current_class;
|
||||
|
||||
static jclass find_class(JNIEnv *env, const char *class_name) {
|
||||
jclass clazz = (*env)->FindClass(env, class_name);
|
||||
if (clazz == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
LOG_FATAL("cannot find %s", class_name);
|
||||
return NULL;
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
|
||||
jmethodID m = (*env)->GetMethodID(env, clazz, name, sig);
|
||||
if (m == 0) {
|
||||
(*env)->ExceptionClear(env);
|
||||
LOG_FATAL("cannot find method %s %s", name, sig);
|
||||
return 0;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static jmethodID find_static_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
|
||||
jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig);
|
||||
if (m == 0) {
|
||||
(*env)->ExceptionClear(env);
|
||||
LOG_FATAL("cannot find method %s %s", name, sig);
|
||||
return 0;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static jmethodID key_rune_method;
|
||||
|
||||
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
JNIEnv* env;
|
||||
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
static int main_running = 0;
|
||||
|
||||
// Entry point from our subclassed NativeActivity.
|
||||
//
|
||||
// By here, the Go runtime has been initialized (as we are running in
|
||||
// -buildmode=c-shared) but the first time it is called, Go's main.main
|
||||
// hasn't been called yet.
|
||||
//
|
||||
// The Activity may be created and destroyed multiple times throughout
|
||||
// the life of a single process. Each time, onCreate is called.
|
||||
void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) {
|
||||
if (!main_running) {
|
||||
JNIEnv* env = activity->env;
|
||||
|
||||
// Note that activity->clazz is mis-named.
|
||||
current_class = (*env)->GetObjectClass(env, activity->clazz);
|
||||
current_class = (*env)->NewGlobalRef(env, current_class);
|
||||
key_rune_method = find_static_method(env, current_class, "getRune", "(III)I");
|
||||
|
||||
setCurrentContext(activity->vm, (*env)->NewGlobalRef(env, activity->clazz));
|
||||
|
||||
// Set TMPDIR.
|
||||
jmethodID gettmpdir = find_method(env, current_class, "getTmpdir", "()Ljava/lang/String;");
|
||||
jstring jpath = (jstring)(*env)->CallObjectMethod(env, activity->clazz, gettmpdir, NULL);
|
||||
const char* tmpdir = (*env)->GetStringUTFChars(env, jpath, NULL);
|
||||
if (setenv("TMPDIR", tmpdir, 1) != 0) {
|
||||
LOG_INFO("setenv(\"TMPDIR\", \"%s\", 1) failed: %d", tmpdir, errno);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jpath, tmpdir);
|
||||
|
||||
// Call the Go main.main.
|
||||
uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main");
|
||||
if (!mainPC) {
|
||||
LOG_FATAL("missing main.main");
|
||||
}
|
||||
callMain(mainPC);
|
||||
main_running = 1;
|
||||
}
|
||||
|
||||
// These functions match the methods on Activity, described at
|
||||
// http://developer.android.com/reference/android/app/Activity.html
|
||||
//
|
||||
// Note that onNativeWindowResized is not called on resize. Avoid it.
|
||||
// https://code.google.com/p/android/issues/detail?id=180645
|
||||
activity->callbacks->onStart = onStart;
|
||||
activity->callbacks->onResume = onResume;
|
||||
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
|
||||
activity->callbacks->onPause = onPause;
|
||||
activity->callbacks->onStop = onStop;
|
||||
activity->callbacks->onDestroy = onDestroy;
|
||||
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
|
||||
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
|
||||
activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
|
||||
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
|
||||
activity->callbacks->onLowMemory = onLowMemory;
|
||||
|
||||
onCreate(activity);
|
||||
}
|
||||
|
||||
// TODO(crawshaw): Test configuration on more devices.
|
||||
static const EGLint RGB_888[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLDisplay display = NULL;
|
||||
EGLSurface surface = NULL;
|
||||
|
||||
static char* initEGLDisplay() {
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (!eglInitialize(display, 0, 0)) {
|
||||
return "EGL initialize failed";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* createEGLSurface(ANativeWindow* window) {
|
||||
char* err;
|
||||
EGLint numConfigs, format;
|
||||
EGLConfig config;
|
||||
EGLContext context;
|
||||
|
||||
if (display == 0) {
|
||||
if ((err = initEGLDisplay()) != NULL) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!eglChooseConfig(display, RGB_888, &config, 1, &numConfigs)) {
|
||||
return "EGL choose RGB_888 config failed";
|
||||
}
|
||||
if (numConfigs <= 0) {
|
||||
return "EGL no config found";
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
if (ANativeWindow_setBuffersGeometry(window, 0, 0, format) != 0) {
|
||||
return "EGL set buffers geometry failed";
|
||||
}
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, window, NULL);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
return "EGL create surface failed";
|
||||
}
|
||||
|
||||
const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
|
||||
|
||||
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
|
||||
return "eglMakeCurrent failed";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* destroyEGLSurface() {
|
||||
if (!eglDestroySurface(display, surface)) {
|
||||
return "EGL destroy surface failed";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t getKeyRune(JNIEnv* env, AInputEvent* e) {
|
||||
return (int32_t)(*env)->CallStaticIntMethod(
|
||||
env,
|
||||
current_class,
|
||||
key_rune_method,
|
||||
AInputEvent_getDeviceId(e),
|
||||
AKeyEvent_getKeyCode(e),
|
||||
AKeyEvent_getMetaState(e)
|
||||
);
|
||||
}
|
824
vendor/github.com/ebitengine/gomobile/app/android.go
generated
vendored
Normal file
824
vendor/github.com/ebitengine/gomobile/app/android.go
generated
vendored
Normal file
@ -0,0 +1,824 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build android
|
||||
|
||||
/*
|
||||
Android Apps are built with -buildmode=c-shared. They are loaded by a
|
||||
running Java process.
|
||||
|
||||
Before any entry point is reached, a global constructor initializes the
|
||||
Go runtime, calling all Go init functions. All cgo calls will block
|
||||
until this is complete. Next JNI_OnLoad is called. When that is
|
||||
complete, one of two entry points is called.
|
||||
|
||||
All-Go apps built using NativeActivity enter at ANativeActivity_onCreate.
|
||||
|
||||
Go libraries (for example, those built with gomobile bind) do not use
|
||||
the app package initialization.
|
||||
*/
|
||||
|
||||
package app
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -landroid -llog -lEGL -lGLESv2
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/input.h>
|
||||
#include <android/keycodes.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
#include <android/native_window.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <jni.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern EGLDisplay display;
|
||||
extern EGLSurface surface;
|
||||
|
||||
|
||||
char* createEGLSurface(ANativeWindow* window);
|
||||
char* destroyEGLSurface();
|
||||
int32_t getKeyRune(JNIEnv* env, AInputEvent* e);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/gomobile/app/internal/callfn"
|
||||
"github.com/ebitengine/gomobile/event/key"
|
||||
"github.com/ebitengine/gomobile/event/lifecycle"
|
||||
"github.com/ebitengine/gomobile/event/paint"
|
||||
"github.com/ebitengine/gomobile/event/size"
|
||||
"github.com/ebitengine/gomobile/event/touch"
|
||||
"github.com/ebitengine/gomobile/geom"
|
||||
"github.com/ebitengine/gomobile/internal/mobileinit"
|
||||
)
|
||||
|
||||
// RunOnJVM runs fn on a new goroutine locked to an OS thread with a JNIEnv.
|
||||
//
|
||||
// RunOnJVM blocks until the call to fn is complete. Any Java
|
||||
// exception or failure to attach to the JVM is returned as an error.
|
||||
//
|
||||
// The function fn takes vm, the current JavaVM*,
|
||||
// env, the current JNIEnv*, and
|
||||
// ctx, a jobject representing the global android.context.Context.
|
||||
func RunOnJVM(fn func(vm, jniEnv, ctx uintptr) error) error {
|
||||
return mobileinit.RunOnJVM(fn)
|
||||
}
|
||||
|
||||
//export setCurrentContext
|
||||
func setCurrentContext(vm *C.JavaVM, ctx C.jobject) {
|
||||
mobileinit.SetCurrentContext(unsafe.Pointer(vm), uintptr(ctx))
|
||||
}
|
||||
|
||||
//export callMain
|
||||
func callMain(mainPC uintptr) {
|
||||
for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} {
|
||||
n := C.CString(name)
|
||||
os.Setenv(name, C.GoString(C.getenv(n)))
|
||||
C.free(unsafe.Pointer(n))
|
||||
}
|
||||
|
||||
// Set timezone.
|
||||
//
|
||||
// Note that Android zoneinfo is stored in /system/usr/share/zoneinfo,
|
||||
// but it is in some kind of packed TZiff file that we do not support
|
||||
// yet. As a stopgap, we build a fixed zone using the tm_zone name.
|
||||
var curtime C.time_t
|
||||
var curtm C.struct_tm
|
||||
C.time(&curtime)
|
||||
C.localtime_r(&curtime, &curtm)
|
||||
tzOffset := int(curtm.tm_gmtoff)
|
||||
tz := C.GoString(curtm.tm_zone)
|
||||
time.Local = time.FixedZone(tz, tzOffset)
|
||||
|
||||
go callfn.CallFn(mainPC)
|
||||
}
|
||||
|
||||
//export onStart
|
||||
func onStart(activity *C.ANativeActivity) {
|
||||
}
|
||||
|
||||
//export onResume
|
||||
func onResume(activity *C.ANativeActivity) {
|
||||
}
|
||||
|
||||
//export onSaveInstanceState
|
||||
func onSaveInstanceState(activity *C.ANativeActivity, outSize *C.size_t) unsafe.Pointer {
|
||||
return nil
|
||||
}
|
||||
|
||||
//export onPause
|
||||
func onPause(activity *C.ANativeActivity) {
|
||||
}
|
||||
|
||||
//export onStop
|
||||
func onStop(activity *C.ANativeActivity) {
|
||||
}
|
||||
|
||||
//export onCreate
|
||||
func onCreate(activity *C.ANativeActivity) {
|
||||
// Set the initial configuration.
|
||||
//
|
||||
// Note we use unbuffered channels to talk to the activity loop, and
|
||||
// NativeActivity calls these callbacks sequentially, so configuration
|
||||
// will be set before <-windowRedrawNeeded is processed.
|
||||
windowConfigChange <- windowConfigRead(activity)
|
||||
}
|
||||
|
||||
//export onDestroy
|
||||
func onDestroy(activity *C.ANativeActivity) {
|
||||
}
|
||||
|
||||
//export onWindowFocusChanged
|
||||
func onWindowFocusChanged(activity *C.ANativeActivity, hasFocus C.int) {
|
||||
}
|
||||
|
||||
//export onNativeWindowCreated
|
||||
func onNativeWindowCreated(activity *C.ANativeActivity, window *C.ANativeWindow) {
|
||||
}
|
||||
|
||||
//export onNativeWindowRedrawNeeded
|
||||
func onNativeWindowRedrawNeeded(activity *C.ANativeActivity, window *C.ANativeWindow) {
|
||||
// Called on orientation change and window resize.
|
||||
// Send a request for redraw, and block this function
|
||||
// until a complete draw and buffer swap is completed.
|
||||
// This is required by the redraw documentation to
|
||||
// avoid bad draws.
|
||||
windowRedrawNeeded <- window
|
||||
<-windowRedrawDone
|
||||
}
|
||||
|
||||
//export onNativeWindowDestroyed
|
||||
func onNativeWindowDestroyed(activity *C.ANativeActivity, window *C.ANativeWindow) {
|
||||
windowDestroyed <- window
|
||||
}
|
||||
|
||||
//export onInputQueueCreated
|
||||
func onInputQueueCreated(activity *C.ANativeActivity, q *C.AInputQueue) {
|
||||
inputQueue <- q
|
||||
<-inputQueueDone
|
||||
}
|
||||
|
||||
//export onInputQueueDestroyed
|
||||
func onInputQueueDestroyed(activity *C.ANativeActivity, q *C.AInputQueue) {
|
||||
inputQueue <- nil
|
||||
<-inputQueueDone
|
||||
}
|
||||
|
||||
//export onContentRectChanged
|
||||
func onContentRectChanged(activity *C.ANativeActivity, rect *C.ARect) {
|
||||
}
|
||||
|
||||
type windowConfig struct {
|
||||
orientation size.Orientation
|
||||
pixelsPerPt float32
|
||||
}
|
||||
|
||||
func windowConfigRead(activity *C.ANativeActivity) windowConfig {
|
||||
aconfig := C.AConfiguration_new()
|
||||
C.AConfiguration_fromAssetManager(aconfig, activity.assetManager)
|
||||
orient := C.AConfiguration_getOrientation(aconfig)
|
||||
density := C.AConfiguration_getDensity(aconfig)
|
||||
C.AConfiguration_delete(aconfig)
|
||||
|
||||
// Calculate the screen resolution. This value is approximate. For example,
|
||||
// a physical resolution of 200 DPI may be quantized to one of the
|
||||
// ACONFIGURATION_DENSITY_XXX values such as 160 or 240.
|
||||
//
|
||||
// A more accurate DPI could possibly be calculated from
|
||||
// https://developer.android.com/reference/android/util/DisplayMetrics.html#xdpi
|
||||
// but this does not appear to be accessible via the NDK. In any case, the
|
||||
// hardware might not even provide a more accurate number, as the system
|
||||
// does not apparently use the reported value. See golang.org/issue/13366
|
||||
// for a discussion.
|
||||
var dpi int
|
||||
switch density {
|
||||
case C.ACONFIGURATION_DENSITY_DEFAULT:
|
||||
dpi = 160
|
||||
case C.ACONFIGURATION_DENSITY_LOW,
|
||||
C.ACONFIGURATION_DENSITY_MEDIUM,
|
||||
213, // C.ACONFIGURATION_DENSITY_TV
|
||||
C.ACONFIGURATION_DENSITY_HIGH,
|
||||
320, // ACONFIGURATION_DENSITY_XHIGH
|
||||
480, // ACONFIGURATION_DENSITY_XXHIGH
|
||||
640: // ACONFIGURATION_DENSITY_XXXHIGH
|
||||
dpi = int(density)
|
||||
case C.ACONFIGURATION_DENSITY_NONE:
|
||||
log.Print("android device reports no screen density")
|
||||
dpi = 72
|
||||
default:
|
||||
log.Printf("android device reports unknown density: %d", density)
|
||||
// All we can do is guess.
|
||||
if density > 0 {
|
||||
dpi = int(density)
|
||||
} else {
|
||||
dpi = 72
|
||||
}
|
||||
}
|
||||
|
||||
o := size.OrientationUnknown
|
||||
switch orient {
|
||||
case C.ACONFIGURATION_ORIENTATION_PORT:
|
||||
o = size.OrientationPortrait
|
||||
case C.ACONFIGURATION_ORIENTATION_LAND:
|
||||
o = size.OrientationLandscape
|
||||
}
|
||||
|
||||
return windowConfig{
|
||||
orientation: o,
|
||||
pixelsPerPt: float32(dpi) / 72,
|
||||
}
|
||||
}
|
||||
|
||||
//export onConfigurationChanged
|
||||
func onConfigurationChanged(activity *C.ANativeActivity) {
|
||||
// A rotation event first triggers onConfigurationChanged, then
|
||||
// calls onNativeWindowRedrawNeeded. We extract the orientation
|
||||
// here and save it for the redraw event.
|
||||
windowConfigChange <- windowConfigRead(activity)
|
||||
}
|
||||
|
||||
//export onLowMemory
|
||||
func onLowMemory(activity *C.ANativeActivity) {
|
||||
}
|
||||
|
||||
var (
|
||||
inputQueue = make(chan *C.AInputQueue)
|
||||
inputQueueDone = make(chan struct{})
|
||||
windowDestroyed = make(chan *C.ANativeWindow)
|
||||
windowRedrawNeeded = make(chan *C.ANativeWindow)
|
||||
windowRedrawDone = make(chan struct{})
|
||||
windowConfigChange = make(chan windowConfig)
|
||||
)
|
||||
|
||||
func init() {
|
||||
theApp.registerGLViewportFilter()
|
||||
}
|
||||
|
||||
func main(f func(App)) {
|
||||
mainUserFn = f
|
||||
// TODO: merge the runInputQueue and mainUI functions?
|
||||
go func() {
|
||||
if err := mobileinit.RunOnJVM(runInputQueue); err != nil {
|
||||
log.Fatalf("app: %v", err)
|
||||
}
|
||||
}()
|
||||
// Preserve this OS thread for:
|
||||
// 1. the attached JNI thread
|
||||
// 2. the GL context
|
||||
if err := mobileinit.RunOnJVM(mainUI); err != nil {
|
||||
log.Fatalf("app: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var mainUserFn func(App)
|
||||
|
||||
func mainUI(vm, jniEnv, ctx uintptr) error {
|
||||
workAvailable := theApp.worker.WorkAvailable()
|
||||
|
||||
donec := make(chan struct{})
|
||||
go func() {
|
||||
// close the donec channel in a defer statement
|
||||
// so that we could still be able to return even
|
||||
// if mainUserFn panics.
|
||||
defer close(donec)
|
||||
|
||||
mainUserFn(theApp)
|
||||
}()
|
||||
|
||||
var pixelsPerPt float32
|
||||
var orientation size.Orientation
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-donec:
|
||||
return nil
|
||||
case cfg := <-windowConfigChange:
|
||||
pixelsPerPt = cfg.pixelsPerPt
|
||||
orientation = cfg.orientation
|
||||
case w := <-windowRedrawNeeded:
|
||||
if C.surface == nil {
|
||||
if errStr := C.createEGLSurface(w); errStr != nil {
|
||||
return fmt.Errorf("%s (%s)", C.GoString(errStr), eglGetError())
|
||||
}
|
||||
}
|
||||
theApp.sendLifecycle(lifecycle.StageFocused)
|
||||
widthPx := int(C.ANativeWindow_getWidth(w))
|
||||
heightPx := int(C.ANativeWindow_getHeight(w))
|
||||
theApp.eventsIn <- size.Event{
|
||||
WidthPx: widthPx,
|
||||
HeightPx: heightPx,
|
||||
WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt),
|
||||
HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt),
|
||||
PixelsPerPt: pixelsPerPt,
|
||||
Orientation: orientation,
|
||||
}
|
||||
theApp.eventsIn <- paint.Event{External: true}
|
||||
case <-windowDestroyed:
|
||||
if C.surface != nil {
|
||||
if errStr := C.destroyEGLSurface(); errStr != nil {
|
||||
return fmt.Errorf("%s (%s)", C.GoString(errStr), eglGetError())
|
||||
}
|
||||
}
|
||||
C.surface = nil
|
||||
theApp.sendLifecycle(lifecycle.StageAlive)
|
||||
case <-workAvailable:
|
||||
theApp.worker.DoWork()
|
||||
case <-theApp.publish:
|
||||
// TODO: compare a generation number to redrawGen for stale paints?
|
||||
if C.surface != nil {
|
||||
// eglSwapBuffers blocks until vsync.
|
||||
if C.eglSwapBuffers(C.display, C.surface) == C.EGL_FALSE {
|
||||
log.Printf("app: failed to swap buffers (%s)", eglGetError())
|
||||
}
|
||||
}
|
||||
select {
|
||||
case windowRedrawDone <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
theApp.publishResult <- PublishResult{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runInputQueue(vm, jniEnv, ctx uintptr) error {
|
||||
env := (*C.JNIEnv)(unsafe.Pointer(jniEnv)) // not a Go heap pointer
|
||||
|
||||
// Android loopers select on OS file descriptors, not Go channels, so we
|
||||
// translate the inputQueue channel to an ALooper_wake call.
|
||||
l := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
|
||||
pending := make(chan *C.AInputQueue, 1)
|
||||
go func() {
|
||||
for q := range inputQueue {
|
||||
pending <- q
|
||||
C.ALooper_wake(l)
|
||||
}
|
||||
}()
|
||||
|
||||
var q *C.AInputQueue
|
||||
for {
|
||||
if C.ALooper_pollOnce(-1, nil, nil, nil) == C.ALOOPER_POLL_WAKE {
|
||||
select {
|
||||
default:
|
||||
case p := <-pending:
|
||||
if q != nil {
|
||||
processEvents(env, q)
|
||||
C.AInputQueue_detachLooper(q)
|
||||
}
|
||||
q = p
|
||||
if q != nil {
|
||||
C.AInputQueue_attachLooper(q, l, 0, nil, nil)
|
||||
}
|
||||
inputQueueDone <- struct{}{}
|
||||
}
|
||||
}
|
||||
if q != nil {
|
||||
processEvents(env, q)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processEvents(env *C.JNIEnv, q *C.AInputQueue) {
|
||||
var e *C.AInputEvent
|
||||
for C.AInputQueue_getEvent(q, &e) >= 0 {
|
||||
if C.AInputQueue_preDispatchEvent(q, e) != 0 {
|
||||
continue
|
||||
}
|
||||
processEvent(env, e)
|
||||
C.AInputQueue_finishEvent(q, e, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func processEvent(env *C.JNIEnv, e *C.AInputEvent) {
|
||||
switch C.AInputEvent_getType(e) {
|
||||
case C.AINPUT_EVENT_TYPE_KEY:
|
||||
processKey(env, e)
|
||||
case C.AINPUT_EVENT_TYPE_MOTION:
|
||||
// At most one of the events in this batch is an up or down event; get its index and change.
|
||||
upDownIndex := C.size_t(C.AMotionEvent_getAction(e)&C.AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> C.AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT
|
||||
upDownType := touch.TypeMove
|
||||
switch C.AMotionEvent_getAction(e) & C.AMOTION_EVENT_ACTION_MASK {
|
||||
case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
upDownType = touch.TypeBegin
|
||||
case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
upDownType = touch.TypeEnd
|
||||
}
|
||||
|
||||
for i, n := C.size_t(0), C.AMotionEvent_getPointerCount(e); i < n; i++ {
|
||||
t := touch.TypeMove
|
||||
if i == upDownIndex {
|
||||
t = upDownType
|
||||
}
|
||||
theApp.eventsIn <- touch.Event{
|
||||
X: float32(C.AMotionEvent_getX(e, i)),
|
||||
Y: float32(C.AMotionEvent_getY(e, i)),
|
||||
Sequence: touch.Sequence(C.AMotionEvent_getPointerId(e, i)),
|
||||
Type: t,
|
||||
}
|
||||
}
|
||||
default:
|
||||
log.Printf("unknown input event, type=%d", C.AInputEvent_getType(e))
|
||||
}
|
||||
}
|
||||
|
||||
func processKey(env *C.JNIEnv, e *C.AInputEvent) {
|
||||
deviceID := C.AInputEvent_getDeviceId(e)
|
||||
if deviceID == 0 {
|
||||
// Software keyboard input, leaving for scribe/IME.
|
||||
return
|
||||
}
|
||||
|
||||
k := key.Event{
|
||||
Rune: rune(C.getKeyRune(env, e)),
|
||||
Code: convAndroidKeyCode(int32(C.AKeyEvent_getKeyCode(e))),
|
||||
}
|
||||
switch C.AKeyEvent_getAction(e) {
|
||||
case C.AKEY_EVENT_ACTION_DOWN:
|
||||
k.Direction = key.DirPress
|
||||
case C.AKEY_EVENT_ACTION_UP:
|
||||
k.Direction = key.DirRelease
|
||||
default:
|
||||
k.Direction = key.DirNone
|
||||
}
|
||||
// TODO(crawshaw): set Modifiers.
|
||||
theApp.eventsIn <- k
|
||||
}
|
||||
|
||||
func eglGetError() string {
|
||||
switch errNum := C.eglGetError(); errNum {
|
||||
case C.EGL_SUCCESS:
|
||||
return "EGL_SUCCESS"
|
||||
case C.EGL_NOT_INITIALIZED:
|
||||
return "EGL_NOT_INITIALIZED"
|
||||
case C.EGL_BAD_ACCESS:
|
||||
return "EGL_BAD_ACCESS"
|
||||
case C.EGL_BAD_ALLOC:
|
||||
return "EGL_BAD_ALLOC"
|
||||
case C.EGL_BAD_ATTRIBUTE:
|
||||
return "EGL_BAD_ATTRIBUTE"
|
||||
case C.EGL_BAD_CONTEXT:
|
||||
return "EGL_BAD_CONTEXT"
|
||||
case C.EGL_BAD_CONFIG:
|
||||
return "EGL_BAD_CONFIG"
|
||||
case C.EGL_BAD_CURRENT_SURFACE:
|
||||
return "EGL_BAD_CURRENT_SURFACE"
|
||||
case C.EGL_BAD_DISPLAY:
|
||||
return "EGL_BAD_DISPLAY"
|
||||
case C.EGL_BAD_SURFACE:
|
||||
return "EGL_BAD_SURFACE"
|
||||
case C.EGL_BAD_MATCH:
|
||||
return "EGL_BAD_MATCH"
|
||||
case C.EGL_BAD_PARAMETER:
|
||||
return "EGL_BAD_PARAMETER"
|
||||
case C.EGL_BAD_NATIVE_PIXMAP:
|
||||
return "EGL_BAD_NATIVE_PIXMAP"
|
||||
case C.EGL_BAD_NATIVE_WINDOW:
|
||||
return "EGL_BAD_NATIVE_WINDOW"
|
||||
case C.EGL_CONTEXT_LOST:
|
||||
return "EGL_CONTEXT_LOST"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown EGL err: %d", errNum)
|
||||
}
|
||||
}
|
||||
|
||||
func convAndroidKeyCode(aKeyCode int32) key.Code {
|
||||
// Many Android key codes do not map into USB HID codes.
|
||||
// For those, key.CodeUnknown is returned. This switch has all
|
||||
// cases, even the unknown ones, to serve as a documentation
|
||||
// and search aid.
|
||||
switch aKeyCode {
|
||||
case C.AKEYCODE_UNKNOWN:
|
||||
case C.AKEYCODE_SOFT_LEFT:
|
||||
case C.AKEYCODE_SOFT_RIGHT:
|
||||
case C.AKEYCODE_HOME:
|
||||
return key.CodeHome
|
||||
case C.AKEYCODE_BACK:
|
||||
case C.AKEYCODE_CALL:
|
||||
case C.AKEYCODE_ENDCALL:
|
||||
case C.AKEYCODE_0:
|
||||
return key.Code0
|
||||
case C.AKEYCODE_1:
|
||||
return key.Code1
|
||||
case C.AKEYCODE_2:
|
||||
return key.Code2
|
||||
case C.AKEYCODE_3:
|
||||
return key.Code3
|
||||
case C.AKEYCODE_4:
|
||||
return key.Code4
|
||||
case C.AKEYCODE_5:
|
||||
return key.Code5
|
||||
case C.AKEYCODE_6:
|
||||
return key.Code6
|
||||
case C.AKEYCODE_7:
|
||||
return key.Code7
|
||||
case C.AKEYCODE_8:
|
||||
return key.Code8
|
||||
case C.AKEYCODE_9:
|
||||
return key.Code9
|
||||
case C.AKEYCODE_STAR:
|
||||
case C.AKEYCODE_POUND:
|
||||
case C.AKEYCODE_DPAD_UP:
|
||||
case C.AKEYCODE_DPAD_DOWN:
|
||||
case C.AKEYCODE_DPAD_LEFT:
|
||||
case C.AKEYCODE_DPAD_RIGHT:
|
||||
case C.AKEYCODE_DPAD_CENTER:
|
||||
case C.AKEYCODE_VOLUME_UP:
|
||||
return key.CodeVolumeUp
|
||||
case C.AKEYCODE_VOLUME_DOWN:
|
||||
return key.CodeVolumeDown
|
||||
case C.AKEYCODE_POWER:
|
||||
case C.AKEYCODE_CAMERA:
|
||||
case C.AKEYCODE_CLEAR:
|
||||
case C.AKEYCODE_A:
|
||||
return key.CodeA
|
||||
case C.AKEYCODE_B:
|
||||
return key.CodeB
|
||||
case C.AKEYCODE_C:
|
||||
return key.CodeC
|
||||
case C.AKEYCODE_D:
|
||||
return key.CodeD
|
||||
case C.AKEYCODE_E:
|
||||
return key.CodeE
|
||||
case C.AKEYCODE_F:
|
||||
return key.CodeF
|
||||
case C.AKEYCODE_G:
|
||||
return key.CodeG
|
||||
case C.AKEYCODE_H:
|
||||
return key.CodeH
|
||||
case C.AKEYCODE_I:
|
||||
return key.CodeI
|
||||
case C.AKEYCODE_J:
|
||||
return key.CodeJ
|
||||
case C.AKEYCODE_K:
|
||||
return key.CodeK
|
||||
case C.AKEYCODE_L:
|
||||
return key.CodeL
|
||||
case C.AKEYCODE_M:
|
||||
return key.CodeM
|
||||
case C.AKEYCODE_N:
|
||||
return key.CodeN
|
||||
case C.AKEYCODE_O:
|
||||
return key.CodeO
|
||||
case C.AKEYCODE_P:
|
||||
return key.CodeP
|
||||
case C.AKEYCODE_Q:
|
||||
return key.CodeQ
|
||||
case C.AKEYCODE_R:
|
||||
return key.CodeR
|
||||
case C.AKEYCODE_S:
|
||||
return key.CodeS
|
||||
case C.AKEYCODE_T:
|
||||
return key.CodeT
|
||||
case C.AKEYCODE_U:
|
||||
return key.CodeU
|
||||
case C.AKEYCODE_V:
|
||||
return key.CodeV
|
||||
case C.AKEYCODE_W:
|
||||
return key.CodeW
|
||||
case C.AKEYCODE_X:
|
||||
return key.CodeX
|
||||
case C.AKEYCODE_Y:
|
||||
return key.CodeY
|
||||
case C.AKEYCODE_Z:
|
||||
return key.CodeZ
|
||||
case C.AKEYCODE_COMMA:
|
||||
return key.CodeComma
|
||||
case C.AKEYCODE_PERIOD:
|
||||
return key.CodeFullStop
|
||||
case C.AKEYCODE_ALT_LEFT:
|
||||
return key.CodeLeftAlt
|
||||
case C.AKEYCODE_ALT_RIGHT:
|
||||
return key.CodeRightAlt
|
||||
case C.AKEYCODE_SHIFT_LEFT:
|
||||
return key.CodeLeftShift
|
||||
case C.AKEYCODE_SHIFT_RIGHT:
|
||||
return key.CodeRightShift
|
||||
case C.AKEYCODE_TAB:
|
||||
return key.CodeTab
|
||||
case C.AKEYCODE_SPACE:
|
||||
return key.CodeSpacebar
|
||||
case C.AKEYCODE_SYM:
|
||||
case C.AKEYCODE_EXPLORER:
|
||||
case C.AKEYCODE_ENVELOPE:
|
||||
case C.AKEYCODE_ENTER:
|
||||
return key.CodeReturnEnter
|
||||
case C.AKEYCODE_DEL:
|
||||
return key.CodeDeleteBackspace
|
||||
case C.AKEYCODE_GRAVE:
|
||||
return key.CodeGraveAccent
|
||||
case C.AKEYCODE_MINUS:
|
||||
return key.CodeHyphenMinus
|
||||
case C.AKEYCODE_EQUALS:
|
||||
return key.CodeEqualSign
|
||||
case C.AKEYCODE_LEFT_BRACKET:
|
||||
return key.CodeLeftSquareBracket
|
||||
case C.AKEYCODE_RIGHT_BRACKET:
|
||||
return key.CodeRightSquareBracket
|
||||
case C.AKEYCODE_BACKSLASH:
|
||||
return key.CodeBackslash
|
||||
case C.AKEYCODE_SEMICOLON:
|
||||
return key.CodeSemicolon
|
||||
case C.AKEYCODE_APOSTROPHE:
|
||||
return key.CodeApostrophe
|
||||
case C.AKEYCODE_SLASH:
|
||||
return key.CodeSlash
|
||||
case C.AKEYCODE_AT:
|
||||
case C.AKEYCODE_NUM:
|
||||
case C.AKEYCODE_HEADSETHOOK:
|
||||
case C.AKEYCODE_FOCUS:
|
||||
case C.AKEYCODE_PLUS:
|
||||
case C.AKEYCODE_MENU:
|
||||
case C.AKEYCODE_NOTIFICATION:
|
||||
case C.AKEYCODE_SEARCH:
|
||||
case C.AKEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case C.AKEYCODE_MEDIA_STOP:
|
||||
case C.AKEYCODE_MEDIA_NEXT:
|
||||
case C.AKEYCODE_MEDIA_PREVIOUS:
|
||||
case C.AKEYCODE_MEDIA_REWIND:
|
||||
case C.AKEYCODE_MEDIA_FAST_FORWARD:
|
||||
case C.AKEYCODE_MUTE:
|
||||
case C.AKEYCODE_PAGE_UP:
|
||||
return key.CodePageUp
|
||||
case C.AKEYCODE_PAGE_DOWN:
|
||||
return key.CodePageDown
|
||||
case C.AKEYCODE_PICTSYMBOLS:
|
||||
case C.AKEYCODE_SWITCH_CHARSET:
|
||||
case C.AKEYCODE_BUTTON_A:
|
||||
case C.AKEYCODE_BUTTON_B:
|
||||
case C.AKEYCODE_BUTTON_C:
|
||||
case C.AKEYCODE_BUTTON_X:
|
||||
case C.AKEYCODE_BUTTON_Y:
|
||||
case C.AKEYCODE_BUTTON_Z:
|
||||
case C.AKEYCODE_BUTTON_L1:
|
||||
case C.AKEYCODE_BUTTON_R1:
|
||||
case C.AKEYCODE_BUTTON_L2:
|
||||
case C.AKEYCODE_BUTTON_R2:
|
||||
case C.AKEYCODE_BUTTON_THUMBL:
|
||||
case C.AKEYCODE_BUTTON_THUMBR:
|
||||
case C.AKEYCODE_BUTTON_START:
|
||||
case C.AKEYCODE_BUTTON_SELECT:
|
||||
case C.AKEYCODE_BUTTON_MODE:
|
||||
case C.AKEYCODE_ESCAPE:
|
||||
return key.CodeEscape
|
||||
case C.AKEYCODE_FORWARD_DEL:
|
||||
return key.CodeDeleteForward
|
||||
case C.AKEYCODE_CTRL_LEFT:
|
||||
return key.CodeLeftControl
|
||||
case C.AKEYCODE_CTRL_RIGHT:
|
||||
return key.CodeRightControl
|
||||
case C.AKEYCODE_CAPS_LOCK:
|
||||
return key.CodeCapsLock
|
||||
case C.AKEYCODE_SCROLL_LOCK:
|
||||
case C.AKEYCODE_META_LEFT:
|
||||
return key.CodeLeftGUI
|
||||
case C.AKEYCODE_META_RIGHT:
|
||||
return key.CodeRightGUI
|
||||
case C.AKEYCODE_FUNCTION:
|
||||
case C.AKEYCODE_SYSRQ:
|
||||
case C.AKEYCODE_BREAK:
|
||||
case C.AKEYCODE_MOVE_HOME:
|
||||
case C.AKEYCODE_MOVE_END:
|
||||
case C.AKEYCODE_INSERT:
|
||||
return key.CodeInsert
|
||||
case C.AKEYCODE_FORWARD:
|
||||
case C.AKEYCODE_MEDIA_PLAY:
|
||||
case C.AKEYCODE_MEDIA_PAUSE:
|
||||
case C.AKEYCODE_MEDIA_CLOSE:
|
||||
case C.AKEYCODE_MEDIA_EJECT:
|
||||
case C.AKEYCODE_MEDIA_RECORD:
|
||||
case C.AKEYCODE_F1:
|
||||
return key.CodeF1
|
||||
case C.AKEYCODE_F2:
|
||||
return key.CodeF2
|
||||
case C.AKEYCODE_F3:
|
||||
return key.CodeF3
|
||||
case C.AKEYCODE_F4:
|
||||
return key.CodeF4
|
||||
case C.AKEYCODE_F5:
|
||||
return key.CodeF5
|
||||
case C.AKEYCODE_F6:
|
||||
return key.CodeF6
|
||||
case C.AKEYCODE_F7:
|
||||
return key.CodeF7
|
||||
case C.AKEYCODE_F8:
|
||||
return key.CodeF8
|
||||
case C.AKEYCODE_F9:
|
||||
return key.CodeF9
|
||||
case C.AKEYCODE_F10:
|
||||
return key.CodeF10
|
||||
case C.AKEYCODE_F11:
|
||||
return key.CodeF11
|
||||
case C.AKEYCODE_F12:
|
||||
return key.CodeF12
|
||||
case C.AKEYCODE_NUM_LOCK:
|
||||
return key.CodeKeypadNumLock
|
||||
case C.AKEYCODE_NUMPAD_0:
|
||||
return key.CodeKeypad0
|
||||
case C.AKEYCODE_NUMPAD_1:
|
||||
return key.CodeKeypad1
|
||||
case C.AKEYCODE_NUMPAD_2:
|
||||
return key.CodeKeypad2
|
||||
case C.AKEYCODE_NUMPAD_3:
|
||||
return key.CodeKeypad3
|
||||
case C.AKEYCODE_NUMPAD_4:
|
||||
return key.CodeKeypad4
|
||||
case C.AKEYCODE_NUMPAD_5:
|
||||
return key.CodeKeypad5
|
||||
case C.AKEYCODE_NUMPAD_6:
|
||||
return key.CodeKeypad6
|
||||
case C.AKEYCODE_NUMPAD_7:
|
||||
return key.CodeKeypad7
|
||||
case C.AKEYCODE_NUMPAD_8:
|
||||
return key.CodeKeypad8
|
||||
case C.AKEYCODE_NUMPAD_9:
|
||||
return key.CodeKeypad9
|
||||
case C.AKEYCODE_NUMPAD_DIVIDE:
|
||||
return key.CodeKeypadSlash
|
||||
case C.AKEYCODE_NUMPAD_MULTIPLY:
|
||||
return key.CodeKeypadAsterisk
|
||||
case C.AKEYCODE_NUMPAD_SUBTRACT:
|
||||
return key.CodeKeypadHyphenMinus
|
||||
case C.AKEYCODE_NUMPAD_ADD:
|
||||
return key.CodeKeypadPlusSign
|
||||
case C.AKEYCODE_NUMPAD_DOT:
|
||||
return key.CodeKeypadFullStop
|
||||
case C.AKEYCODE_NUMPAD_COMMA:
|
||||
case C.AKEYCODE_NUMPAD_ENTER:
|
||||
return key.CodeKeypadEnter
|
||||
case C.AKEYCODE_NUMPAD_EQUALS:
|
||||
return key.CodeKeypadEqualSign
|
||||
case C.AKEYCODE_NUMPAD_LEFT_PAREN:
|
||||
case C.AKEYCODE_NUMPAD_RIGHT_PAREN:
|
||||
case C.AKEYCODE_VOLUME_MUTE:
|
||||
return key.CodeMute
|
||||
case C.AKEYCODE_INFO:
|
||||
case C.AKEYCODE_CHANNEL_UP:
|
||||
case C.AKEYCODE_CHANNEL_DOWN:
|
||||
case C.AKEYCODE_ZOOM_IN:
|
||||
case C.AKEYCODE_ZOOM_OUT:
|
||||
case C.AKEYCODE_TV:
|
||||
case C.AKEYCODE_WINDOW:
|
||||
case C.AKEYCODE_GUIDE:
|
||||
case C.AKEYCODE_DVR:
|
||||
case C.AKEYCODE_BOOKMARK:
|
||||
case C.AKEYCODE_CAPTIONS:
|
||||
case C.AKEYCODE_SETTINGS:
|
||||
case C.AKEYCODE_TV_POWER:
|
||||
case C.AKEYCODE_TV_INPUT:
|
||||
case C.AKEYCODE_STB_POWER:
|
||||
case C.AKEYCODE_STB_INPUT:
|
||||
case C.AKEYCODE_AVR_POWER:
|
||||
case C.AKEYCODE_AVR_INPUT:
|
||||
case C.AKEYCODE_PROG_RED:
|
||||
case C.AKEYCODE_PROG_GREEN:
|
||||
case C.AKEYCODE_PROG_YELLOW:
|
||||
case C.AKEYCODE_PROG_BLUE:
|
||||
case C.AKEYCODE_APP_SWITCH:
|
||||
case C.AKEYCODE_BUTTON_1:
|
||||
case C.AKEYCODE_BUTTON_2:
|
||||
case C.AKEYCODE_BUTTON_3:
|
||||
case C.AKEYCODE_BUTTON_4:
|
||||
case C.AKEYCODE_BUTTON_5:
|
||||
case C.AKEYCODE_BUTTON_6:
|
||||
case C.AKEYCODE_BUTTON_7:
|
||||
case C.AKEYCODE_BUTTON_8:
|
||||
case C.AKEYCODE_BUTTON_9:
|
||||
case C.AKEYCODE_BUTTON_10:
|
||||
case C.AKEYCODE_BUTTON_11:
|
||||
case C.AKEYCODE_BUTTON_12:
|
||||
case C.AKEYCODE_BUTTON_13:
|
||||
case C.AKEYCODE_BUTTON_14:
|
||||
case C.AKEYCODE_BUTTON_15:
|
||||
case C.AKEYCODE_BUTTON_16:
|
||||
case C.AKEYCODE_LANGUAGE_SWITCH:
|
||||
case C.AKEYCODE_MANNER_MODE:
|
||||
case C.AKEYCODE_3D_MODE:
|
||||
case C.AKEYCODE_CONTACTS:
|
||||
case C.AKEYCODE_CALENDAR:
|
||||
case C.AKEYCODE_MUSIC:
|
||||
case C.AKEYCODE_CALCULATOR:
|
||||
}
|
||||
/* Defined in an NDK API version beyond what we use today:
|
||||
C.AKEYCODE_ASSIST
|
||||
C.AKEYCODE_BRIGHTNESS_DOWN
|
||||
C.AKEYCODE_BRIGHTNESS_UP
|
||||
C.AKEYCODE_EISU
|
||||
C.AKEYCODE_HENKAN
|
||||
C.AKEYCODE_KANA
|
||||
C.AKEYCODE_KATAKANA_HIRAGANA
|
||||
C.AKEYCODE_MEDIA_AUDIO_TRACK
|
||||
C.AKEYCODE_MUHENKAN
|
||||
C.AKEYCODE_RO
|
||||
C.AKEYCODE_YEN
|
||||
C.AKEYCODE_ZENKAKU_HANKAKU
|
||||
*/
|
||||
return key.CodeUnknown
|
||||
}
|
213
vendor/github.com/ebitengine/gomobile/app/app.go
generated
vendored
Normal file
213
vendor/github.com/ebitengine/gomobile/app/app.go
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux || darwin || windows
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/ebitengine/gomobile/event/lifecycle"
|
||||
"github.com/ebitengine/gomobile/event/size"
|
||||
"github.com/ebitengine/gomobile/gl"
|
||||
_ "github.com/ebitengine/gomobile/internal/mobileinit"
|
||||
)
|
||||
|
||||
// Main is called by the main.main function to run the mobile application.
|
||||
//
|
||||
// It calls f on the App, in a separate goroutine, as some OS-specific
|
||||
// libraries require being on 'the main thread'.
|
||||
func Main(f func(App)) {
|
||||
main(f)
|
||||
}
|
||||
|
||||
// App is how a GUI mobile application interacts with the OS.
|
||||
type App interface {
|
||||
// Events returns the events channel. It carries events from the system to
|
||||
// the app. The type of such events include:
|
||||
// - lifecycle.Event
|
||||
// - mouse.Event
|
||||
// - paint.Event
|
||||
// - size.Event
|
||||
// - touch.Event
|
||||
// from the github.com/ebitengine/gomobile/event/etc packages. Other packages may
|
||||
// define other event types that are carried on this channel.
|
||||
Events() <-chan interface{}
|
||||
|
||||
// Send sends an event on the events channel. It does not block.
|
||||
Send(event interface{})
|
||||
|
||||
// Publish flushes any pending drawing commands, such as OpenGL calls, and
|
||||
// swaps the back buffer to the screen.
|
||||
Publish() PublishResult
|
||||
|
||||
// TODO: replace filters (and the Events channel) with a NextEvent method?
|
||||
|
||||
// Filter calls each registered event filter function in sequence.
|
||||
Filter(event interface{}) interface{}
|
||||
|
||||
// RegisterFilter registers a event filter function to be called by Filter. The
|
||||
// function can return a different event, or return nil to consume the event,
|
||||
// but the function can also return its argument unchanged, where its purpose
|
||||
// is to trigger a side effect rather than modify the event.
|
||||
RegisterFilter(f func(interface{}) interface{})
|
||||
}
|
||||
|
||||
// PublishResult is the result of an App.Publish call.
|
||||
type PublishResult struct {
|
||||
// BackBufferPreserved is whether the contents of the back buffer was
|
||||
// preserved. If false, the contents are undefined.
|
||||
BackBufferPreserved bool
|
||||
}
|
||||
|
||||
var theApp = &app{
|
||||
eventsOut: make(chan interface{}),
|
||||
lifecycleStage: lifecycle.StageDead,
|
||||
publish: make(chan struct{}),
|
||||
publishResult: make(chan PublishResult),
|
||||
}
|
||||
|
||||
func init() {
|
||||
theApp.eventsIn = pump(theApp.eventsOut)
|
||||
theApp.glctx, theApp.worker = gl.NewContext()
|
||||
}
|
||||
|
||||
func (a *app) sendLifecycle(to lifecycle.Stage) {
|
||||
if a.lifecycleStage == to {
|
||||
return
|
||||
}
|
||||
a.eventsIn <- lifecycle.Event{
|
||||
From: a.lifecycleStage,
|
||||
To: to,
|
||||
DrawContext: a.glctx,
|
||||
}
|
||||
a.lifecycleStage = to
|
||||
}
|
||||
|
||||
type app struct {
|
||||
filters []func(interface{}) interface{}
|
||||
|
||||
eventsOut chan interface{}
|
||||
eventsIn chan interface{}
|
||||
lifecycleStage lifecycle.Stage
|
||||
publish chan struct{}
|
||||
publishResult chan PublishResult
|
||||
|
||||
glctx gl.Context
|
||||
worker gl.Worker
|
||||
}
|
||||
|
||||
func (a *app) Events() <-chan interface{} {
|
||||
return a.eventsOut
|
||||
}
|
||||
|
||||
func (a *app) Send(event interface{}) {
|
||||
a.eventsIn <- event
|
||||
}
|
||||
|
||||
func (a *app) Publish() PublishResult {
|
||||
// gl.Flush is a lightweight (on modern GL drivers) blocking call
|
||||
// that ensures all GL functions pending in the gl package have
|
||||
// been passed onto the GL driver before the app package attempts
|
||||
// to swap the screen buffer.
|
||||
//
|
||||
// This enforces that the final receive (for this paint cycle) on
|
||||
// gl.WorkAvailable happens before the send on endPaint.
|
||||
a.glctx.Flush()
|
||||
a.publish <- struct{}{}
|
||||
return <-a.publishResult
|
||||
}
|
||||
|
||||
func (a *app) Filter(event interface{}) interface{} {
|
||||
for _, f := range a.filters {
|
||||
event = f(event)
|
||||
}
|
||||
return event
|
||||
}
|
||||
|
||||
func (a *app) RegisterFilter(f func(interface{}) interface{}) {
|
||||
a.filters = append(a.filters, f)
|
||||
}
|
||||
|
||||
type stopPumping struct{}
|
||||
|
||||
// pump returns a channel src such that sending on src will eventually send on
|
||||
// dst, in order, but that src will always be ready to send/receive soon, even
|
||||
// if dst currently isn't. It is effectively an infinitely buffered channel.
|
||||
//
|
||||
// In particular, goroutine A sending on src will not deadlock even if goroutine
|
||||
// B that's responsible for receiving on dst is currently blocked trying to
|
||||
// send to A on a separate channel.
|
||||
//
|
||||
// Send a stopPumping on the src channel to close the dst channel after all queued
|
||||
// events are sent on dst. After that, other goroutines can still send to src,
|
||||
// so that such sends won't block forever, but such events will be ignored.
|
||||
func pump(dst chan interface{}) (src chan interface{}) {
|
||||
src = make(chan interface{})
|
||||
go func() {
|
||||
// initialSize is the initial size of the circular buffer. It must be a
|
||||
// power of 2.
|
||||
const initialSize = 16
|
||||
i, j, buf, mask := 0, 0, make([]interface{}, initialSize), initialSize-1
|
||||
|
||||
srcActive := true
|
||||
for {
|
||||
maybeDst := dst
|
||||
if i == j {
|
||||
maybeDst = nil
|
||||
}
|
||||
if maybeDst == nil && !srcActive {
|
||||
// Pump is stopped and empty.
|
||||
break
|
||||
}
|
||||
|
||||
select {
|
||||
case maybeDst <- buf[i&mask]:
|
||||
buf[i&mask] = nil
|
||||
i++
|
||||
|
||||
case e := <-src:
|
||||
if _, ok := e.(stopPumping); ok {
|
||||
srcActive = false
|
||||
continue
|
||||
}
|
||||
|
||||
if !srcActive {
|
||||
continue
|
||||
}
|
||||
|
||||
// Allocate a bigger buffer if necessary.
|
||||
if i+len(buf) == j {
|
||||
b := make([]interface{}, 2*len(buf))
|
||||
n := copy(b, buf[j&mask:])
|
||||
copy(b[n:], buf[:j&mask])
|
||||
i, j = 0, len(buf)
|
||||
buf, mask = b, len(b)-1
|
||||
}
|
||||
|
||||
buf[j&mask] = e
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
close(dst)
|
||||
// Block forever.
|
||||
for range src {
|
||||
}
|
||||
}()
|
||||
return src
|
||||
}
|
||||
|
||||
// TODO: do this for all build targets, not just linux (x11 and Android)? If
|
||||
// so, should package gl instead of this package call RegisterFilter??
|
||||
//
|
||||
// TODO: does Android need this?? It seems to work without it (Nexus 7,
|
||||
// KitKat). If only x11 needs this, should we move this to x11.go??
|
||||
func (a *app) registerGLViewportFilter() {
|
||||
a.RegisterFilter(func(e interface{}) interface{} {
|
||||
if e, ok := e.(size.Event); ok {
|
||||
a.glctx.Viewport(0, 0, e.WidthPx, e.HeightPx)
|
||||
}
|
||||
return e
|
||||
})
|
||||
}
|
13
vendor/github.com/ebitengine/gomobile/app/app_windows.go
generated
vendored
Normal file
13
vendor/github.com/ebitengine/gomobile/app/app_windows.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func main(f func(a App)) {
|
||||
log.Fatal("main is not implemented on Windows")
|
||||
}
|
495
vendor/github.com/ebitengine/gomobile/app/darwin_desktop.go
generated
vendored
Normal file
495
vendor/github.com/ebitengine/gomobile/app/darwin_desktop.go
generated
vendored
Normal file
@ -0,0 +1,495 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && !ios
|
||||
|
||||
package app
|
||||
|
||||
// Simple on-screen app debugging for OS X. Not an officially supported
|
||||
// development target for apps, as screens with mice are very different
|
||||
// than screens with touch panels.
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION
|
||||
#cgo LDFLAGS: -framework Cocoa -framework OpenGL
|
||||
#import <Carbon/Carbon.h> // for HIToolbox/Events.h
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void runApp(void);
|
||||
void stopApp(void);
|
||||
void makeCurrentContext(GLintptr);
|
||||
uint64 threadID();
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/ebitengine/gomobile/event/key"
|
||||
"github.com/ebitengine/gomobile/event/lifecycle"
|
||||
"github.com/ebitengine/gomobile/event/paint"
|
||||
"github.com/ebitengine/gomobile/event/size"
|
||||
"github.com/ebitengine/gomobile/event/touch"
|
||||
"github.com/ebitengine/gomobile/geom"
|
||||
)
|
||||
|
||||
var initThreadID uint64
|
||||
|
||||
func init() {
|
||||
// Lock the goroutine responsible for initialization to an OS thread.
|
||||
// This means the goroutine running main (and calling runApp below)
|
||||
// is locked to the OS thread that started the program. This is
|
||||
// necessary for the correct delivery of Cocoa events to the process.
|
||||
//
|
||||
// A discussion on this topic:
|
||||
// https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ
|
||||
runtime.LockOSThread()
|
||||
initThreadID = uint64(C.threadID())
|
||||
}
|
||||
|
||||
func main(f func(App)) {
|
||||
if tid := uint64(C.threadID()); tid != initThreadID {
|
||||
log.Fatalf("app.Main called on thread %d, but app.init ran on %d", tid, initThreadID)
|
||||
}
|
||||
|
||||
go func() {
|
||||
f(theApp)
|
||||
C.stopApp()
|
||||
}()
|
||||
|
||||
C.runApp()
|
||||
}
|
||||
|
||||
// loop is the primary drawing loop.
|
||||
//
|
||||
// After Cocoa has captured the initial OS thread for processing Cocoa
|
||||
// events in runApp, it starts loop on another goroutine. It is locked
|
||||
// to an OS thread for its OpenGL context.
|
||||
//
|
||||
// The loop processes GL calls until a publish event appears.
|
||||
// Then it runs any remaining GL calls and flushes the screen.
|
||||
//
|
||||
// As NSOpenGLCPSwapInterval is set to 1, the call to CGLFlushDrawable
|
||||
// blocks until the screen refresh.
|
||||
func (a *app) loop(ctx C.GLintptr) {
|
||||
runtime.LockOSThread()
|
||||
C.makeCurrentContext(ctx)
|
||||
|
||||
workAvailable := a.worker.WorkAvailable()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-workAvailable:
|
||||
a.worker.DoWork()
|
||||
case <-theApp.publish:
|
||||
loop1:
|
||||
for {
|
||||
select {
|
||||
case <-workAvailable:
|
||||
a.worker.DoWork()
|
||||
default:
|
||||
break loop1
|
||||
}
|
||||
}
|
||||
C.CGLFlushDrawable(C.CGLGetCurrentContext())
|
||||
theApp.publishResult <- PublishResult{}
|
||||
select {
|
||||
case drawDone <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var drawDone = make(chan struct{})
|
||||
|
||||
// drawgl is used by Cocoa to occasionally request screen updates.
|
||||
//
|
||||
//export drawgl
|
||||
func drawgl() {
|
||||
switch theApp.lifecycleStage {
|
||||
case lifecycle.StageFocused, lifecycle.StageVisible:
|
||||
theApp.Send(paint.Event{
|
||||
External: true,
|
||||
})
|
||||
<-drawDone
|
||||
}
|
||||
}
|
||||
|
||||
//export startloop
|
||||
func startloop(ctx C.GLintptr) {
|
||||
go theApp.loop(ctx)
|
||||
}
|
||||
|
||||
var windowHeightPx float32
|
||||
|
||||
//export setGeom
|
||||
func setGeom(pixelsPerPt float32, widthPx, heightPx int) {
|
||||
windowHeightPx = float32(heightPx)
|
||||
theApp.eventsIn <- size.Event{
|
||||
WidthPx: widthPx,
|
||||
HeightPx: heightPx,
|
||||
WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt),
|
||||
HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt),
|
||||
PixelsPerPt: pixelsPerPt,
|
||||
}
|
||||
}
|
||||
|
||||
var touchEvents struct {
|
||||
sync.Mutex
|
||||
pending []touch.Event
|
||||
}
|
||||
|
||||
func sendTouch(t touch.Type, x, y float32) {
|
||||
theApp.eventsIn <- touch.Event{
|
||||
X: x,
|
||||
Y: windowHeightPx - y,
|
||||
Sequence: 0,
|
||||
Type: t,
|
||||
}
|
||||
}
|
||||
|
||||
//export eventMouseDown
|
||||
func eventMouseDown(x, y float32) { sendTouch(touch.TypeBegin, x, y) }
|
||||
|
||||
//export eventMouseDragged
|
||||
func eventMouseDragged(x, y float32) { sendTouch(touch.TypeMove, x, y) }
|
||||
|
||||
//export eventMouseEnd
|
||||
func eventMouseEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) }
|
||||
|
||||
//export lifecycleDead
|
||||
func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) }
|
||||
|
||||
//export eventKey
|
||||
func eventKey(runeVal int32, direction uint8, code uint16, flags uint32) {
|
||||
var modifiers key.Modifiers
|
||||
for _, mod := range mods {
|
||||
if flags&mod.flags == mod.flags {
|
||||
modifiers |= mod.mod
|
||||
}
|
||||
}
|
||||
|
||||
theApp.eventsIn <- key.Event{
|
||||
Rune: convRune(rune(runeVal)),
|
||||
Code: convVirtualKeyCode(code),
|
||||
Modifiers: modifiers,
|
||||
Direction: key.Direction(direction),
|
||||
}
|
||||
}
|
||||
|
||||
//export eventFlags
|
||||
func eventFlags(flags uint32) {
|
||||
for _, mod := range mods {
|
||||
if flags&mod.flags == mod.flags && lastFlags&mod.flags != mod.flags {
|
||||
eventKey(-1, uint8(key.DirPress), mod.code, flags)
|
||||
}
|
||||
if lastFlags&mod.flags == mod.flags && flags&mod.flags != mod.flags {
|
||||
eventKey(-1, uint8(key.DirRelease), mod.code, flags)
|
||||
}
|
||||
}
|
||||
lastFlags = flags
|
||||
}
|
||||
|
||||
var lastFlags uint32
|
||||
|
||||
var mods = [...]struct {
|
||||
flags uint32
|
||||
code uint16
|
||||
mod key.Modifiers
|
||||
}{
|
||||
// Left and right variants of modifier keys have their own masks,
|
||||
// but they are not documented. These were determined empirically.
|
||||
{1<<17 | 0x102, C.kVK_Shift, key.ModShift},
|
||||
{1<<17 | 0x104, C.kVK_RightShift, key.ModShift},
|
||||
{1<<18 | 0x101, C.kVK_Control, key.ModControl},
|
||||
// TODO key.ControlRight
|
||||
{1<<19 | 0x120, C.kVK_Option, key.ModAlt},
|
||||
{1<<19 | 0x140, C.kVK_RightOption, key.ModAlt},
|
||||
{1<<20 | 0x108, C.kVK_Command, key.ModMeta},
|
||||
{1<<20 | 0x110, C.kVK_Command, key.ModMeta}, // TODO: missing kVK_RightCommand
|
||||
}
|
||||
|
||||
//export lifecycleAlive
|
||||
func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) }
|
||||
|
||||
//export lifecycleVisible
|
||||
func lifecycleVisible() {
|
||||
theApp.sendLifecycle(lifecycle.StageVisible)
|
||||
}
|
||||
|
||||
//export lifecycleFocused
|
||||
func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) }
|
||||
|
||||
// convRune marks the Carbon/Cocoa private-range unicode rune representing
|
||||
// a non-unicode key event to -1, used for Rune in the key package.
|
||||
//
|
||||
// http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT
|
||||
func convRune(r rune) rune {
|
||||
if '\uE000' <= r && r <= '\uF8FF' {
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// convVirtualKeyCode converts a Carbon/Cocoa virtual key code number
|
||||
// into the standard keycodes used by the key package.
|
||||
//
|
||||
// To get a sense of the key map, see the diagram on
|
||||
//
|
||||
// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes
|
||||
func convVirtualKeyCode(vkcode uint16) key.Code {
|
||||
switch vkcode {
|
||||
case C.kVK_ANSI_A:
|
||||
return key.CodeA
|
||||
case C.kVK_ANSI_B:
|
||||
return key.CodeB
|
||||
case C.kVK_ANSI_C:
|
||||
return key.CodeC
|
||||
case C.kVK_ANSI_D:
|
||||
return key.CodeD
|
||||
case C.kVK_ANSI_E:
|
||||
return key.CodeE
|
||||
case C.kVK_ANSI_F:
|
||||
return key.CodeF
|
||||
case C.kVK_ANSI_G:
|
||||
return key.CodeG
|
||||
case C.kVK_ANSI_H:
|
||||
return key.CodeH
|
||||
case C.kVK_ANSI_I:
|
||||
return key.CodeI
|
||||
case C.kVK_ANSI_J:
|
||||
return key.CodeJ
|
||||
case C.kVK_ANSI_K:
|
||||
return key.CodeK
|
||||
case C.kVK_ANSI_L:
|
||||
return key.CodeL
|
||||
case C.kVK_ANSI_M:
|
||||
return key.CodeM
|
||||
case C.kVK_ANSI_N:
|
||||
return key.CodeN
|
||||
case C.kVK_ANSI_O:
|
||||
return key.CodeO
|
||||
case C.kVK_ANSI_P:
|
||||
return key.CodeP
|
||||
case C.kVK_ANSI_Q:
|
||||
return key.CodeQ
|
||||
case C.kVK_ANSI_R:
|
||||
return key.CodeR
|
||||
case C.kVK_ANSI_S:
|
||||
return key.CodeS
|
||||
case C.kVK_ANSI_T:
|
||||
return key.CodeT
|
||||
case C.kVK_ANSI_U:
|
||||
return key.CodeU
|
||||
case C.kVK_ANSI_V:
|
||||
return key.CodeV
|
||||
case C.kVK_ANSI_W:
|
||||
return key.CodeW
|
||||
case C.kVK_ANSI_X:
|
||||
return key.CodeX
|
||||
case C.kVK_ANSI_Y:
|
||||
return key.CodeY
|
||||
case C.kVK_ANSI_Z:
|
||||
return key.CodeZ
|
||||
case C.kVK_ANSI_1:
|
||||
return key.Code1
|
||||
case C.kVK_ANSI_2:
|
||||
return key.Code2
|
||||
case C.kVK_ANSI_3:
|
||||
return key.Code3
|
||||
case C.kVK_ANSI_4:
|
||||
return key.Code4
|
||||
case C.kVK_ANSI_5:
|
||||
return key.Code5
|
||||
case C.kVK_ANSI_6:
|
||||
return key.Code6
|
||||
case C.kVK_ANSI_7:
|
||||
return key.Code7
|
||||
case C.kVK_ANSI_8:
|
||||
return key.Code8
|
||||
case C.kVK_ANSI_9:
|
||||
return key.Code9
|
||||
case C.kVK_ANSI_0:
|
||||
return key.Code0
|
||||
// TODO: move the rest of these codes to constants in key.go
|
||||
// if we are happy with them.
|
||||
case C.kVK_Return:
|
||||
return key.CodeReturnEnter
|
||||
case C.kVK_Escape:
|
||||
return key.CodeEscape
|
||||
case C.kVK_Delete:
|
||||
return key.CodeDeleteBackspace
|
||||
case C.kVK_Tab:
|
||||
return key.CodeTab
|
||||
case C.kVK_Space:
|
||||
return key.CodeSpacebar
|
||||
case C.kVK_ANSI_Minus:
|
||||
return key.CodeHyphenMinus
|
||||
case C.kVK_ANSI_Equal:
|
||||
return key.CodeEqualSign
|
||||
case C.kVK_ANSI_LeftBracket:
|
||||
return key.CodeLeftSquareBracket
|
||||
case C.kVK_ANSI_RightBracket:
|
||||
return key.CodeRightSquareBracket
|
||||
case C.kVK_ANSI_Backslash:
|
||||
return key.CodeBackslash
|
||||
// 50: Keyboard Non-US "#" and ~
|
||||
case C.kVK_ANSI_Semicolon:
|
||||
return key.CodeSemicolon
|
||||
case C.kVK_ANSI_Quote:
|
||||
return key.CodeApostrophe
|
||||
case C.kVK_ANSI_Grave:
|
||||
return key.CodeGraveAccent
|
||||
case C.kVK_ANSI_Comma:
|
||||
return key.CodeComma
|
||||
case C.kVK_ANSI_Period:
|
||||
return key.CodeFullStop
|
||||
case C.kVK_ANSI_Slash:
|
||||
return key.CodeSlash
|
||||
case C.kVK_CapsLock:
|
||||
return key.CodeCapsLock
|
||||
case C.kVK_F1:
|
||||
return key.CodeF1
|
||||
case C.kVK_F2:
|
||||
return key.CodeF2
|
||||
case C.kVK_F3:
|
||||
return key.CodeF3
|
||||
case C.kVK_F4:
|
||||
return key.CodeF4
|
||||
case C.kVK_F5:
|
||||
return key.CodeF5
|
||||
case C.kVK_F6:
|
||||
return key.CodeF6
|
||||
case C.kVK_F7:
|
||||
return key.CodeF7
|
||||
case C.kVK_F8:
|
||||
return key.CodeF8
|
||||
case C.kVK_F9:
|
||||
return key.CodeF9
|
||||
case C.kVK_F10:
|
||||
return key.CodeF10
|
||||
case C.kVK_F11:
|
||||
return key.CodeF11
|
||||
case C.kVK_F12:
|
||||
return key.CodeF12
|
||||
// 70: PrintScreen
|
||||
// 71: Scroll Lock
|
||||
// 72: Pause
|
||||
// 73: Insert
|
||||
case C.kVK_Home:
|
||||
return key.CodeHome
|
||||
case C.kVK_PageUp:
|
||||
return key.CodePageUp
|
||||
case C.kVK_ForwardDelete:
|
||||
return key.CodeDeleteForward
|
||||
case C.kVK_End:
|
||||
return key.CodeEnd
|
||||
case C.kVK_PageDown:
|
||||
return key.CodePageDown
|
||||
case C.kVK_RightArrow:
|
||||
return key.CodeRightArrow
|
||||
case C.kVK_LeftArrow:
|
||||
return key.CodeLeftArrow
|
||||
case C.kVK_DownArrow:
|
||||
return key.CodeDownArrow
|
||||
case C.kVK_UpArrow:
|
||||
return key.CodeUpArrow
|
||||
case C.kVK_ANSI_KeypadClear:
|
||||
return key.CodeKeypadNumLock
|
||||
case C.kVK_ANSI_KeypadDivide:
|
||||
return key.CodeKeypadSlash
|
||||
case C.kVK_ANSI_KeypadMultiply:
|
||||
return key.CodeKeypadAsterisk
|
||||
case C.kVK_ANSI_KeypadMinus:
|
||||
return key.CodeKeypadHyphenMinus
|
||||
case C.kVK_ANSI_KeypadPlus:
|
||||
return key.CodeKeypadPlusSign
|
||||
case C.kVK_ANSI_KeypadEnter:
|
||||
return key.CodeKeypadEnter
|
||||
case C.kVK_ANSI_Keypad1:
|
||||
return key.CodeKeypad1
|
||||
case C.kVK_ANSI_Keypad2:
|
||||
return key.CodeKeypad2
|
||||
case C.kVK_ANSI_Keypad3:
|
||||
return key.CodeKeypad3
|
||||
case C.kVK_ANSI_Keypad4:
|
||||
return key.CodeKeypad4
|
||||
case C.kVK_ANSI_Keypad5:
|
||||
return key.CodeKeypad5
|
||||
case C.kVK_ANSI_Keypad6:
|
||||
return key.CodeKeypad6
|
||||
case C.kVK_ANSI_Keypad7:
|
||||
return key.CodeKeypad7
|
||||
case C.kVK_ANSI_Keypad8:
|
||||
return key.CodeKeypad8
|
||||
case C.kVK_ANSI_Keypad9:
|
||||
return key.CodeKeypad9
|
||||
case C.kVK_ANSI_Keypad0:
|
||||
return key.CodeKeypad0
|
||||
case C.kVK_ANSI_KeypadDecimal:
|
||||
return key.CodeKeypadFullStop
|
||||
case C.kVK_ANSI_KeypadEquals:
|
||||
return key.CodeKeypadEqualSign
|
||||
case C.kVK_F13:
|
||||
return key.CodeF13
|
||||
case C.kVK_F14:
|
||||
return key.CodeF14
|
||||
case C.kVK_F15:
|
||||
return key.CodeF15
|
||||
case C.kVK_F16:
|
||||
return key.CodeF16
|
||||
case C.kVK_F17:
|
||||
return key.CodeF17
|
||||
case C.kVK_F18:
|
||||
return key.CodeF18
|
||||
case C.kVK_F19:
|
||||
return key.CodeF19
|
||||
case C.kVK_F20:
|
||||
return key.CodeF20
|
||||
// 116: Keyboard Execute
|
||||
case C.kVK_Help:
|
||||
return key.CodeHelp
|
||||
// 118: Keyboard Menu
|
||||
// 119: Keyboard Select
|
||||
// 120: Keyboard Stop
|
||||
// 121: Keyboard Again
|
||||
// 122: Keyboard Undo
|
||||
// 123: Keyboard Cut
|
||||
// 124: Keyboard Copy
|
||||
// 125: Keyboard Paste
|
||||
// 126: Keyboard Find
|
||||
case C.kVK_Mute:
|
||||
return key.CodeMute
|
||||
case C.kVK_VolumeUp:
|
||||
return key.CodeVolumeUp
|
||||
case C.kVK_VolumeDown:
|
||||
return key.CodeVolumeDown
|
||||
// 130: Keyboard Locking Caps Lock
|
||||
// 131: Keyboard Locking Num Lock
|
||||
// 132: Keyboard Locking Scroll Lock
|
||||
// 133: Keyboard Comma
|
||||
// 134: Keyboard Equal Sign
|
||||
// ...: Bunch of stuff
|
||||
case C.kVK_Control:
|
||||
return key.CodeLeftControl
|
||||
case C.kVK_Shift:
|
||||
return key.CodeLeftShift
|
||||
case C.kVK_Option:
|
||||
return key.CodeLeftAlt
|
||||
case C.kVK_Command:
|
||||
return key.CodeLeftGUI
|
||||
case C.kVK_RightControl:
|
||||
return key.CodeRightControl
|
||||
case C.kVK_RightShift:
|
||||
return key.CodeRightShift
|
||||
case C.kVK_RightOption:
|
||||
return key.CodeRightAlt
|
||||
// TODO key.CodeRightGUI
|
||||
default:
|
||||
return key.CodeUnknown
|
||||
}
|
||||
}
|
251
vendor/github.com/ebitengine/gomobile/app/darwin_desktop.m
generated
vendored
Normal file
251
vendor/github.com/ebitengine/gomobile/app/darwin_desktop.m
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && !ios
|
||||
// +build darwin
|
||||
// +build !ios
|
||||
|
||||
#include "_cgo_export.h"
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <OpenGL/gl3.h>
|
||||
|
||||
void makeCurrentContext(GLintptr context) {
|
||||
NSOpenGLContext* ctx = (NSOpenGLContext*)context;
|
||||
[ctx makeCurrentContext];
|
||||
}
|
||||
|
||||
uint64 threadID() {
|
||||
uint64 id;
|
||||
if (pthread_threadid_np(pthread_self(), &id)) {
|
||||
abort();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@interface MobileGLView : NSOpenGLView<NSApplicationDelegate, NSWindowDelegate>
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MobileGLView
|
||||
- (void)prepareOpenGL {
|
||||
[super prepareOpenGL];
|
||||
[self setWantsBestResolutionOpenGLSurface:YES];
|
||||
GLint swapInt = 1;
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
// Using attribute arrays in OpenGL 3.3 requires the use of a VBA.
|
||||
// But VBAs don't exist in ES 2. So we bind a default one.
|
||||
GLuint vba;
|
||||
glGenVertexArrays(1, &vba);
|
||||
glBindVertexArray(vba);
|
||||
|
||||
startloop((GLintptr)[self openGLContext]);
|
||||
}
|
||||
|
||||
- (void)reshape {
|
||||
[super reshape];
|
||||
|
||||
// Calculate screen PPI.
|
||||
//
|
||||
// Note that the backingScaleFactor converts from logical
|
||||
// pixels to actual pixels, but both of these units vary
|
||||
// independently from real world size. E.g.
|
||||
//
|
||||
// 13" Retina Macbook Pro, 2560x1600, 227ppi, backingScaleFactor=2, scale=3.15
|
||||
// 15" Retina Macbook Pro, 2880x1800, 220ppi, backingScaleFactor=2, scale=3.06
|
||||
// 27" iMac, 2560x1440, 109ppi, backingScaleFactor=1, scale=1.51
|
||||
// 27" Retina iMac, 5120x2880, 218ppi, backingScaleFactor=2, scale=3.03
|
||||
NSScreen *screen = [NSScreen mainScreen];
|
||||
double screenPixW = [screen frame].size.width * [screen backingScaleFactor];
|
||||
|
||||
CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue];
|
||||
CGSize screenSizeMM = CGDisplayScreenSize(display); // in millimeters
|
||||
float ppi = 25.4 * screenPixW / screenSizeMM.width;
|
||||
float pixelsPerPt = ppi/72.0;
|
||||
|
||||
// The width and height reported to the geom package are the
|
||||
// bounds of the OpenGL view. Several steps are necessary.
|
||||
// First, [self bounds] gives us the number of logical pixels
|
||||
// in the view. Multiplying this by the backingScaleFactor
|
||||
// gives us the number of actual pixels.
|
||||
NSRect r = [self bounds];
|
||||
int w = r.size.width * [screen backingScaleFactor];
|
||||
int h = r.size.height * [screen backingScaleFactor];
|
||||
|
||||
setGeom(pixelsPerPt, w, h);
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)theRect {
|
||||
// Called during resize. This gets rid of flicker when resizing.
|
||||
drawgl();
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)theEvent {
|
||||
double scale = [[NSScreen mainScreen] backingScaleFactor];
|
||||
NSPoint p = [theEvent locationInWindow];
|
||||
eventMouseDown(p.x * scale, p.y * scale);
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent *)theEvent {
|
||||
double scale = [[NSScreen mainScreen] backingScaleFactor];
|
||||
NSPoint p = [theEvent locationInWindow];
|
||||
eventMouseEnd(p.x * scale, p.y * scale);
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)theEvent {
|
||||
double scale = [[NSScreen mainScreen] backingScaleFactor];
|
||||
NSPoint p = [theEvent locationInWindow];
|
||||
eventMouseDragged(p.x * scale, p.y * scale);
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification *)notification {
|
||||
lifecycleFocused();
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification *)notification {
|
||||
if (![NSApp isHidden]) {
|
||||
lifecycleVisible();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
lifecycleAlive();
|
||||
[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
lifecycleVisible();
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||
lifecycleDead();
|
||||
}
|
||||
|
||||
- (void)applicationDidHide:(NSNotification *)aNotification {
|
||||
lifecycleAlive();
|
||||
}
|
||||
|
||||
- (void)applicationWillUnhide:(NSNotification *)notification {
|
||||
lifecycleVisible();
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification {
|
||||
lifecycleAlive();
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MobileResponder : NSResponder
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MobileResponder
|
||||
- (void)keyDown:(NSEvent *)theEvent {
|
||||
[self key:theEvent];
|
||||
}
|
||||
- (void)keyUp:(NSEvent *)theEvent {
|
||||
[self key:theEvent];
|
||||
}
|
||||
- (void)key:(NSEvent *)theEvent {
|
||||
NSRange range = [theEvent.characters rangeOfComposedCharacterSequenceAtIndex:0];
|
||||
|
||||
uint8_t buf[4] = {0, 0, 0, 0};
|
||||
if (![theEvent.characters getBytes:buf
|
||||
maxLength:4
|
||||
usedLength:nil
|
||||
encoding:NSUTF32LittleEndianStringEncoding
|
||||
options:NSStringEncodingConversionAllowLossy
|
||||
range:range
|
||||
remainingRange:nil]) {
|
||||
NSLog(@"failed to read key event %@", theEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t rune = (uint32_t)buf[0]<<0 | (uint32_t)buf[1]<<8 | (uint32_t)buf[2]<<16 | (uint32_t)buf[3]<<24;
|
||||
|
||||
uint8_t direction;
|
||||
if ([theEvent isARepeat]) {
|
||||
direction = 0;
|
||||
} else if (theEvent.type == NSEventTypeKeyDown) {
|
||||
direction = 1;
|
||||
} else {
|
||||
direction = 2;
|
||||
}
|
||||
eventKey((int32_t)rune, direction, theEvent.keyCode, theEvent.modifierFlags);
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)theEvent {
|
||||
eventFlags(theEvent.modifierFlags);
|
||||
}
|
||||
@end
|
||||
|
||||
void
|
||||
runApp(void) {
|
||||
[NSAutoreleasePool new];
|
||||
[NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
id menuBar = [[NSMenu new] autorelease];
|
||||
id menuItem = [[NSMenuItem new] autorelease];
|
||||
[menuBar addItem:menuItem];
|
||||
[NSApp setMainMenu:menuBar];
|
||||
|
||||
id menu = [[NSMenu new] autorelease];
|
||||
id name = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
id hideMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Hide"
|
||||
action:@selector(hide:) keyEquivalent:@"h"]
|
||||
autorelease];
|
||||
[menu addItem:hideMenuItem];
|
||||
|
||||
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Quit"
|
||||
action:@selector(terminate:) keyEquivalent:@"q"]
|
||||
autorelease];
|
||||
[menu addItem:quitMenuItem];
|
||||
[menuItem setSubmenu:menu];
|
||||
|
||||
NSRect rect = NSMakeRect(0, 0, 600, 800);
|
||||
|
||||
NSWindow* window = [[[NSWindow alloc] initWithContentRect:rect
|
||||
styleMask:NSWindowStyleMaskTitled
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO]
|
||||
autorelease];
|
||||
window.styleMask |= NSWindowStyleMaskResizable;
|
||||
window.styleMask |= NSWindowStyleMaskMiniaturizable;
|
||||
window.styleMask |= NSWindowStyleMaskClosable;
|
||||
window.title = name;
|
||||
[window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
|
||||
|
||||
NSOpenGLPixelFormatAttribute attr[] = {
|
||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||
NSOpenGLPFAColorSize, 24,
|
||||
NSOpenGLPFAAlphaSize, 8,
|
||||
NSOpenGLPFADepthSize, 16,
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFAAllowOfflineRenderers,
|
||||
0
|
||||
};
|
||||
id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
||||
MobileGLView* view = [[MobileGLView alloc] initWithFrame:rect pixelFormat:pixFormat];
|
||||
[window setContentView:view];
|
||||
[window setDelegate:view];
|
||||
[NSApp setDelegate:view];
|
||||
|
||||
window.nextResponder = [[[MobileResponder alloc] init] autorelease];
|
||||
|
||||
[NSApp run];
|
||||
}
|
||||
|
||||
void stopApp(void) {
|
||||
[NSApp terminate:nil];
|
||||
}
|
215
vendor/github.com/ebitengine/gomobile/app/darwin_ios.go
generated
vendored
Normal file
215
vendor/github.com/ebitengine/gomobile/app/darwin_ios.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && ios
|
||||
|
||||
package app
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION -DGLES_SILENCE_DEPRECATION
|
||||
#cgo LDFLAGS: -framework Foundation -framework UIKit -framework GLKit -framework OpenGLES -framework QuartzCore
|
||||
#include <sys/utsname.h>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <UIKit/UIDevice.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
extern struct utsname sysInfo;
|
||||
|
||||
void runApp(void);
|
||||
void makeCurrentContext(GLintptr ctx);
|
||||
void swapBuffers(GLintptr ctx);
|
||||
uint64_t threadID();
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ebitengine/gomobile/event/lifecycle"
|
||||
"github.com/ebitengine/gomobile/event/paint"
|
||||
"github.com/ebitengine/gomobile/event/size"
|
||||
"github.com/ebitengine/gomobile/event/touch"
|
||||
"github.com/ebitengine/gomobile/geom"
|
||||
)
|
||||
|
||||
var initThreadID uint64
|
||||
|
||||
func init() {
|
||||
// Lock the goroutine responsible for initialization to an OS thread.
|
||||
// This means the goroutine running main (and calling the run function
|
||||
// below) is locked to the OS thread that started the program. This is
|
||||
// necessary for the correct delivery of UIKit events to the process.
|
||||
//
|
||||
// A discussion on this topic:
|
||||
// https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ
|
||||
runtime.LockOSThread()
|
||||
initThreadID = uint64(C.threadID())
|
||||
}
|
||||
|
||||
func main(f func(App)) {
|
||||
if tid := uint64(C.threadID()); tid != initThreadID {
|
||||
log.Fatalf("app.Run called on thread %d, but app.init ran on %d", tid, initThreadID)
|
||||
}
|
||||
|
||||
go func() {
|
||||
f(theApp)
|
||||
// TODO(crawshaw): trigger runApp to return
|
||||
}()
|
||||
C.runApp()
|
||||
panic("unexpected return from app.runApp")
|
||||
}
|
||||
|
||||
var pixelsPerPt float32
|
||||
var screenScale int // [UIScreen mainScreen].scale, either 1, 2, or 3.
|
||||
|
||||
//export setScreen
|
||||
func setScreen(scale int) {
|
||||
C.uname(&C.sysInfo)
|
||||
name := C.GoString(&C.sysInfo.machine[0])
|
||||
|
||||
var v float32
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(name, "iPhone"):
|
||||
v = 163
|
||||
case strings.HasPrefix(name, "iPad"):
|
||||
// TODO: is there a better way to distinguish the iPad Mini?
|
||||
switch name {
|
||||
case "iPad2,5", "iPad2,6", "iPad2,7", "iPad4,4", "iPad4,5", "iPad4,6", "iPad4,7":
|
||||
v = 163 // iPad Mini
|
||||
default:
|
||||
v = 132
|
||||
}
|
||||
default:
|
||||
v = 163 // names like i386 and x86_64 are the simulator
|
||||
}
|
||||
|
||||
if v == 0 {
|
||||
log.Printf("unknown machine: %s", name)
|
||||
v = 163 // emergency fallback
|
||||
}
|
||||
|
||||
pixelsPerPt = v * float32(scale) / 72
|
||||
screenScale = scale
|
||||
}
|
||||
|
||||
//export updateConfig
|
||||
func updateConfig(width, height, orientation int32) {
|
||||
o := size.OrientationUnknown
|
||||
switch orientation {
|
||||
case C.UIDeviceOrientationPortrait, C.UIDeviceOrientationPortraitUpsideDown:
|
||||
o = size.OrientationPortrait
|
||||
case C.UIDeviceOrientationLandscapeLeft, C.UIDeviceOrientationLandscapeRight:
|
||||
o = size.OrientationLandscape
|
||||
}
|
||||
widthPx := screenScale * int(width)
|
||||
heightPx := screenScale * int(height)
|
||||
theApp.eventsIn <- size.Event{
|
||||
WidthPx: widthPx,
|
||||
HeightPx: heightPx,
|
||||
WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt),
|
||||
HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt),
|
||||
PixelsPerPt: pixelsPerPt,
|
||||
Orientation: o,
|
||||
}
|
||||
theApp.eventsIn <- paint.Event{External: true}
|
||||
}
|
||||
|
||||
// touchIDs is the current active touches. The position in the array
|
||||
// is the ID, the value is the UITouch* pointer value.
|
||||
//
|
||||
// It is widely reported that the iPhone can handle up to 5 simultaneous
|
||||
// touch events, while the iPad can handle 11.
|
||||
var touchIDs [11]uintptr
|
||||
|
||||
var touchEvents struct {
|
||||
sync.Mutex
|
||||
pending []touch.Event
|
||||
}
|
||||
|
||||
//export sendTouch
|
||||
func sendTouch(cTouch, cTouchType uintptr, x, y float32) {
|
||||
id := -1
|
||||
for i, val := range touchIDs {
|
||||
if val == cTouch {
|
||||
id = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if id == -1 {
|
||||
for i, val := range touchIDs {
|
||||
if val == 0 {
|
||||
touchIDs[i] = cTouch
|
||||
id = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if id == -1 {
|
||||
panic("out of touchIDs")
|
||||
}
|
||||
}
|
||||
|
||||
t := touch.Type(cTouchType)
|
||||
if t == touch.TypeEnd {
|
||||
touchIDs[id] = 0
|
||||
}
|
||||
|
||||
theApp.eventsIn <- touch.Event{
|
||||
X: x,
|
||||
Y: y,
|
||||
Sequence: touch.Sequence(id),
|
||||
Type: t,
|
||||
}
|
||||
}
|
||||
|
||||
//export lifecycleDead
|
||||
func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) }
|
||||
|
||||
//export lifecycleAlive
|
||||
func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) }
|
||||
|
||||
//export lifecycleVisible
|
||||
func lifecycleVisible() { theApp.sendLifecycle(lifecycle.StageVisible) }
|
||||
|
||||
//export lifecycleFocused
|
||||
func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) }
|
||||
|
||||
//export startloop
|
||||
func startloop(ctx C.GLintptr) {
|
||||
go theApp.loop(ctx)
|
||||
}
|
||||
|
||||
// loop is the primary drawing loop.
|
||||
//
|
||||
// After UIKit has captured the initial OS thread for processing UIKit
|
||||
// events in runApp, it starts loop on another goroutine. It is locked
|
||||
// to an OS thread for its OpenGL context.
|
||||
func (a *app) loop(ctx C.GLintptr) {
|
||||
runtime.LockOSThread()
|
||||
C.makeCurrentContext(ctx)
|
||||
|
||||
workAvailable := a.worker.WorkAvailable()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-workAvailable:
|
||||
a.worker.DoWork()
|
||||
case <-theApp.publish:
|
||||
loop1:
|
||||
for {
|
||||
select {
|
||||
case <-workAvailable:
|
||||
a.worker.DoWork()
|
||||
default:
|
||||
break loop1
|
||||
}
|
||||
}
|
||||
C.swapBuffers(ctx)
|
||||
theApp.publishResult <- PublishResult{}
|
||||
}
|
||||
}
|
||||
}
|
167
vendor/github.com/ebitengine/gomobile/app/darwin_ios.m
generated
vendored
Normal file
167
vendor/github.com/ebitengine/gomobile/app/darwin_ios.m
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && ios
|
||||
// +build darwin
|
||||
// +build ios
|
||||
|
||||
#include "_cgo_export.h"
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
struct utsname sysInfo;
|
||||
|
||||
@interface GoAppAppController : GLKViewController<UIContentContainer, GLKViewDelegate>
|
||||
@end
|
||||
|
||||
@interface GoAppAppDelegate : UIResponder<UIApplicationDelegate>
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
@property (strong, nonatomic) GoAppAppController *controller;
|
||||
@end
|
||||
|
||||
@implementation GoAppAppDelegate
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
lifecycleAlive();
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.controller = [[GoAppAppController alloc] initWithNibName:nil bundle:nil];
|
||||
self.window.rootViewController = self.controller;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication * )application {
|
||||
lifecycleFocused();
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
lifecycleVisible();
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
lifecycleAlive();
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
lifecycleDead();
|
||||
}
|
||||
@end
|
||||
|
||||
@interface GoAppAppController ()
|
||||
@property (strong, nonatomic) EAGLContext *context;
|
||||
@property (strong, nonatomic) GLKView *glview;
|
||||
@end
|
||||
|
||||
@implementation GoAppAppController
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
// TODO: replace by swapping out GLKViewController for a UIVIewController.
|
||||
[super viewWillAppear:animated];
|
||||
self.paused = YES;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
self.glview = (GLKView*)self.view;
|
||||
self.glview.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
self.glview.multipleTouchEnabled = true; // TODO expose setting to user.
|
||||
self.glview.context = self.context;
|
||||
self.glview.userInteractionEnabled = YES;
|
||||
self.glview.enableSetNeedsDisplay = YES; // only invoked once
|
||||
|
||||
// Do not use the GLKViewController draw loop.
|
||||
self.paused = YES;
|
||||
self.resumeOnDidBecomeActive = NO;
|
||||
self.preferredFramesPerSecond = 0;
|
||||
|
||||
int scale = 1;
|
||||
if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)]) {
|
||||
scale = (int)[UIScreen mainScreen].scale; // either 1.0, 2.0, or 3.0.
|
||||
}
|
||||
setScreen(scale);
|
||||
|
||||
CGSize size = [UIScreen mainScreen].bounds.size;
|
||||
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
updateConfig((int)size.width, (int)size.height, orientation);
|
||||
}
|
||||
|
||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
||||
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
||||
// TODO(crawshaw): come up with a plan to handle animations.
|
||||
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
||||
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
updateConfig((int)size.width, (int)size.height, orientation);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
|
||||
// Now that we have been asked to do the first draw, disable any
|
||||
// future draw and hand control over to the Go paint.Event cycle.
|
||||
self.glview.enableSetNeedsDisplay = NO;
|
||||
startloop((GLintptr)self.context);
|
||||
}
|
||||
|
||||
#define TOUCH_TYPE_BEGIN 0 // touch.TypeBegin
|
||||
#define TOUCH_TYPE_MOVE 1 // touch.TypeMove
|
||||
#define TOUCH_TYPE_END 2 // touch.TypeEnd
|
||||
|
||||
static void sendTouches(int change, NSSet* touches) {
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
for (UITouch* touch in touches) {
|
||||
CGPoint p = [touch locationInView:touch.view];
|
||||
sendTouch((GoUintptr)touch, (GoUintptr)change, p.x*scale, p.y*scale);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
sendTouches(TOUCH_TYPE_BEGIN, touches);
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
sendTouches(TOUCH_TYPE_MOVE, touches);
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
sendTouches(TOUCH_TYPE_END, touches);
|
||||
}
|
||||
|
||||
- (void)touchesCanceled:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
sendTouches(TOUCH_TYPE_END, touches);
|
||||
}
|
||||
@end
|
||||
|
||||
void runApp(void) {
|
||||
char* argv[] = {};
|
||||
@autoreleasepool {
|
||||
UIApplicationMain(0, argv, nil, NSStringFromClass([GoAppAppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
||||
void makeCurrentContext(GLintptr context) {
|
||||
EAGLContext* ctx = (EAGLContext*)context;
|
||||
if (![EAGLContext setCurrentContext:ctx]) {
|
||||
// TODO(crawshaw): determine how terrible this is. Exit?
|
||||
NSLog(@"failed to set current context");
|
||||
}
|
||||
}
|
||||
|
||||
void swapBuffers(GLintptr context) {
|
||||
__block EAGLContext* ctx = (EAGLContext*)context;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[EAGLContext setCurrentContext:ctx];
|
||||
[ctx presentRenderbuffer:GL_RENDERBUFFER];
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t threadID() {
|
||||
uint64_t id;
|
||||
if (pthread_threadid_np(pthread_self(), &id)) {
|
||||
abort();
|
||||
}
|
||||
return id;
|
||||
}
|
88
vendor/github.com/ebitengine/gomobile/app/doc.go
generated
vendored
Normal file
88
vendor/github.com/ebitengine/gomobile/app/doc.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package app lets you write portable all-Go apps for Android and iOS.
|
||||
|
||||
There are typically two ways to use Go on Android and iOS. The first
|
||||
is to write a Go library and use `gomobile bind` to generate language
|
||||
bindings for Java and Objective-C. Building a library does not
|
||||
require the app package. The `gomobile bind` command produces output
|
||||
that you can include in an Android Studio or Xcode project. For more
|
||||
on language bindings, see https://github.com/ebitengine/gomobile/cmd/gobind.
|
||||
|
||||
The second way is to write an app entirely in Go. The APIs are limited
|
||||
to those that are portable between both Android and iOS, in particular
|
||||
OpenGL, audio, and other Android NDK-like APIs. An all-Go app should
|
||||
use this app package to initialize the app, manage its lifecycle, and
|
||||
receive events.
|
||||
|
||||
# Building apps
|
||||
|
||||
Apps written entirely in Go have a main function, and can be built
|
||||
with `gomobile build`, which directly produces runnable output for
|
||||
Android and iOS.
|
||||
|
||||
The gomobile tool can get installed with go get. For reference, see
|
||||
https://github.com/ebitengine/gomobile/cmd/gomobile.
|
||||
|
||||
For detailed instructions and documentation, see
|
||||
https://golang.org/wiki/Mobile.
|
||||
|
||||
# Event processing in Native Apps
|
||||
|
||||
The Go runtime is initialized on Android when NativeActivity onCreate is
|
||||
called, and on iOS when the process starts. In both cases, Go init functions
|
||||
run before the app lifecycle has started.
|
||||
|
||||
An app is expected to call the Main function in main.main. When the function
|
||||
exits, the app exits. Inside the func passed to Main, call Filter on every
|
||||
event received, and then switch on its type. Registered filters run when the
|
||||
event is received, not when it is sent, so that filters run in the same
|
||||
goroutine as other code that calls OpenGL.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/ebitengine/gomobile/app"
|
||||
"github.com/ebitengine/gomobile/event/lifecycle"
|
||||
"github.com/ebitengine/gomobile/event/paint"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app.Main(func(a app.App) {
|
||||
for e := range a.Events() {
|
||||
switch e := a.Filter(e).(type) {
|
||||
case lifecycle.Event:
|
||||
// ...
|
||||
case paint.Event:
|
||||
log.Print("Call OpenGL here.")
|
||||
a.Publish()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
An event is represented by the empty interface type interface{}. Any value can
|
||||
be an event. Commonly used types include Event types defined by the following
|
||||
packages:
|
||||
- github.com/ebitengine/gomobile/event/lifecycle
|
||||
- github.com/ebitengine/gomobile/event/mouse
|
||||
- github.com/ebitengine/gomobile/event/paint
|
||||
- github.com/ebitengine/gomobile/event/size
|
||||
- github.com/ebitengine/gomobile/event/touch
|
||||
|
||||
For example, touch.Event is the type that represents touch events. Other
|
||||
packages may define their own events, and send them on an app's event channel.
|
||||
|
||||
Other packages can also register event filters, e.g. to manage resources in
|
||||
response to lifecycle events. Such packages should call:
|
||||
|
||||
app.RegisterFilter(etc)
|
||||
|
||||
in an init function inside that package.
|
||||
*/
|
||||
package app // import "github.com/ebitengine/gomobile/app"
|
16
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn.go
generated
vendored
Normal file
16
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build android && (arm || 386 || amd64 || arm64)
|
||||
|
||||
// Package callfn provides an android entry point.
|
||||
//
|
||||
// It is a separate package from app because it contains Go assembly,
|
||||
// which does not compile in a package using cgo.
|
||||
package callfn
|
||||
|
||||
// CallFn calls a zero-argument function by its program counter.
|
||||
// It is only intended for calling main.main. Using it for
|
||||
// anything else will not end well.
|
||||
func CallFn(fn uintptr)
|
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_386.s
generated
vendored
Normal file
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_386.s
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
TEXT ·CallFn(SB),$0-4
|
||||
MOVL fn+0(FP), AX
|
||||
CALL AX
|
||||
RET
|
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_amd64.s
generated
vendored
Normal file
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_amd64.s
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
TEXT ·CallFn(SB),$0-8
|
||||
MOVQ fn+0(FP), AX
|
||||
CALL AX
|
||||
RET
|
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_arm.s
generated
vendored
Normal file
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_arm.s
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
TEXT ·CallFn(SB),$0-4
|
||||
MOVW fn+0(FP), R0
|
||||
BL (R0)
|
||||
RET
|
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_arm64.s
generated
vendored
Normal file
11
vendor/github.com/ebitengine/gomobile/app/internal/callfn/callfn_arm64.s
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "textflag.h"
|
||||
#include "funcdata.h"
|
||||
|
||||
TEXT ·CallFn(SB),$0-8
|
||||
MOVD fn+0(FP), R0
|
||||
BL (R0)
|
||||
RET
|
175
vendor/github.com/ebitengine/gomobile/app/x11.c
generated
vendored
Normal file
175
vendor/github.com/ebitengine/gomobile/app/x11.c
generated
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && !android
|
||||
// +build linux,!android
|
||||
|
||||
#include "_cgo_export.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static Atom wm_delete_window;
|
||||
|
||||
static Window
|
||||
new_window(Display *x_dpy, EGLDisplay e_dpy, int w, int h, EGLContext *ctx, EGLSurface *surf) {
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
if (!eglChooseConfig(e_dpy, attribs, &config, 1, &num_configs)) {
|
||||
fprintf(stderr, "eglChooseConfig failed\n");
|
||||
exit(1);
|
||||
}
|
||||
EGLint vid;
|
||||
if (!eglGetConfigAttrib(e_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
fprintf(stderr, "eglGetConfigAttrib failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XVisualInfo visTemplate;
|
||||
visTemplate.visualid = vid;
|
||||
int num_visuals;
|
||||
XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
fprintf(stderr, "XGetVisualInfo failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Window root = RootWindow(x_dpy, DefaultScreen(x_dpy));
|
||||
XSetWindowAttributes attr;
|
||||
|
||||
attr.colormap = XCreateColormap(x_dpy, root, visInfo->visual, AllocNone);
|
||||
if (!attr.colormap) {
|
||||
fprintf(stderr, "XCreateColormap failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask |
|
||||
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask;
|
||||
Window win = XCreateWindow(
|
||||
x_dpy, root, 0, 0, w, h, 0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, CWColormap | CWEventMask, &attr);
|
||||
XFree(visInfo);
|
||||
|
||||
XSizeHints sizehints;
|
||||
sizehints.width = w;
|
||||
sizehints.height = h;
|
||||
sizehints.flags = USSize;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, "App", "App", None, (char **)NULL, 0, &sizehints);
|
||||
|
||||
static const EGLint ctx_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
*ctx = eglCreateContext(e_dpy, config, EGL_NO_CONTEXT, ctx_attribs);
|
||||
if (!*ctx) {
|
||||
fprintf(stderr, "eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
*surf = eglCreateWindowSurface(e_dpy, config, win, NULL);
|
||||
if (!*surf) {
|
||||
fprintf(stderr, "eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
return win;
|
||||
}
|
||||
|
||||
Display *x_dpy;
|
||||
EGLDisplay e_dpy;
|
||||
EGLContext e_ctx;
|
||||
EGLSurface e_surf;
|
||||
Window win;
|
||||
|
||||
void
|
||||
createWindow(void) {
|
||||
x_dpy = XOpenDisplay(NULL);
|
||||
if (!x_dpy) {
|
||||
fprintf(stderr, "XOpenDisplay failed\n");
|
||||
exit(1);
|
||||
}
|
||||
e_dpy = eglGetDisplay(x_dpy);
|
||||
if (!e_dpy) {
|
||||
fprintf(stderr, "eglGetDisplay failed\n");
|
||||
exit(1);
|
||||
}
|
||||
EGLint e_major, e_minor;
|
||||
if (!eglInitialize(e_dpy, &e_major, &e_minor)) {
|
||||
fprintf(stderr, "eglInitialize failed\n");
|
||||
exit(1);
|
||||
}
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
win = new_window(x_dpy, e_dpy, 600, 800, &e_ctx, &e_surf);
|
||||
|
||||
wm_delete_window = XInternAtom(x_dpy, "WM_DELETE_WINDOW", True);
|
||||
if (wm_delete_window != None) {
|
||||
XSetWMProtocols(x_dpy, win, &wm_delete_window, 1);
|
||||
}
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(e_dpy, e_surf, e_surf, e_ctx)) {
|
||||
fprintf(stderr, "eglMakeCurrent failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Window size and DPI should be initialized before starting app.
|
||||
XEvent ev;
|
||||
while (1) {
|
||||
if (XCheckMaskEvent(x_dpy, StructureNotifyMask, &ev) == False) {
|
||||
continue;
|
||||
}
|
||||
if (ev.type == ConfigureNotify) {
|
||||
onResize(ev.xconfigure.width, ev.xconfigure.height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
processEvents(void) {
|
||||
while (XPending(x_dpy)) {
|
||||
XEvent ev;
|
||||
XNextEvent(x_dpy, &ev);
|
||||
switch (ev.type) {
|
||||
case ButtonPress:
|
||||
onTouchBegin((float)ev.xbutton.x, (float)ev.xbutton.y);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
onTouchEnd((float)ev.xbutton.x, (float)ev.xbutton.y);
|
||||
break;
|
||||
case MotionNotify:
|
||||
onTouchMove((float)ev.xmotion.x, (float)ev.xmotion.y);
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
onResize(ev.xconfigure.width, ev.xconfigure.height);
|
||||
break;
|
||||
case ClientMessage:
|
||||
if (wm_delete_window != None && (Atom)ev.xclient.data.l[0] == wm_delete_window) {
|
||||
onStop();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
swapBuffers(void) {
|
||||
if (eglSwapBuffers(e_dpy, e_surf) == EGL_FALSE) {
|
||||
fprintf(stderr, "eglSwapBuffer failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
126
vendor/github.com/ebitengine/gomobile/app/x11.go
generated
vendored
Normal file
126
vendor/github.com/ebitengine/gomobile/app/x11.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && !android
|
||||
|
||||
package app
|
||||
|
||||
/*
|
||||
Simple on-screen app debugging for X11. Not an officially supported
|
||||
development target for apps, as screens with mice are very different
|
||||
than screens with touch panels.
|
||||
*/
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lEGL -lGLESv2 -lX11
|
||||
|
||||
void createWindow(void);
|
||||
void processEvents(void);
|
||||
void swapBuffers(void);
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/ebitengine/gomobile/event/lifecycle"
|
||||
"github.com/ebitengine/gomobile/event/paint"
|
||||
"github.com/ebitengine/gomobile/event/size"
|
||||
"github.com/ebitengine/gomobile/event/touch"
|
||||
"github.com/ebitengine/gomobile/geom"
|
||||
)
|
||||
|
||||
func init() {
|
||||
theApp.registerGLViewportFilter()
|
||||
}
|
||||
|
||||
func main(f func(App)) {
|
||||
runtime.LockOSThread()
|
||||
|
||||
workAvailable := theApp.worker.WorkAvailable()
|
||||
|
||||
C.createWindow()
|
||||
|
||||
// TODO: send lifecycle events when e.g. the X11 window is iconified or moved off-screen.
|
||||
theApp.sendLifecycle(lifecycle.StageFocused)
|
||||
|
||||
// TODO: translate X11 expose events to shiny paint events, instead of
|
||||
// sending this synthetic paint event as a hack.
|
||||
theApp.eventsIn <- paint.Event{}
|
||||
|
||||
donec := make(chan struct{})
|
||||
go func() {
|
||||
// close the donec channel in a defer statement
|
||||
// so that we could still be able to return even
|
||||
// if f panics.
|
||||
defer close(donec)
|
||||
|
||||
f(theApp)
|
||||
}()
|
||||
|
||||
// TODO: can we get the actual vsync signal?
|
||||
ticker := time.NewTicker(time.Second / 60)
|
||||
defer ticker.Stop()
|
||||
var tc <-chan time.Time
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-donec:
|
||||
return
|
||||
case <-workAvailable:
|
||||
theApp.worker.DoWork()
|
||||
case <-theApp.publish:
|
||||
C.swapBuffers()
|
||||
tc = ticker.C
|
||||
case <-tc:
|
||||
tc = nil
|
||||
theApp.publishResult <- PublishResult{}
|
||||
}
|
||||
C.processEvents()
|
||||
}
|
||||
}
|
||||
|
||||
//export onResize
|
||||
func onResize(w, h int) {
|
||||
// TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM
|
||||
// is probably the best place to start looking.
|
||||
pixelsPerPt := float32(1)
|
||||
theApp.eventsIn <- size.Event{
|
||||
WidthPx: w,
|
||||
HeightPx: h,
|
||||
WidthPt: geom.Pt(w),
|
||||
HeightPt: geom.Pt(h),
|
||||
PixelsPerPt: pixelsPerPt,
|
||||
}
|
||||
}
|
||||
|
||||
func sendTouch(t touch.Type, x, y float32) {
|
||||
theApp.eventsIn <- touch.Event{
|
||||
X: x,
|
||||
Y: y,
|
||||
Sequence: 0, // TODO: button??
|
||||
Type: t,
|
||||
}
|
||||
}
|
||||
|
||||
//export onTouchBegin
|
||||
func onTouchBegin(x, y float32) { sendTouch(touch.TypeBegin, x, y) }
|
||||
|
||||
//export onTouchMove
|
||||
func onTouchMove(x, y float32) { sendTouch(touch.TypeMove, x, y) }
|
||||
|
||||
//export onTouchEnd
|
||||
func onTouchEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) }
|
||||
|
||||
var stopped bool
|
||||
|
||||
//export onStop
|
||||
func onStop() {
|
||||
if stopped {
|
||||
return
|
||||
}
|
||||
stopped = true
|
||||
theApp.sendLifecycle(lifecycle.StageDead)
|
||||
theApp.eventsIn <- stopPumping{}
|
||||
}
|
60
vendor/github.com/ebitengine/gomobile/event/key/code_string.go
generated
vendored
Normal file
60
vendor/github.com/ebitengine/gomobile/event/key/code_string.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
// Code generated by "stringer -type=Code"; DO NOT EDIT
|
||||
|
||||
package key
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
_Code_name_0 = "CodeUnknown"
|
||||
_Code_name_1 = "CodeACodeBCodeCCodeDCodeECodeFCodeGCodeHCodeICodeJCodeKCodeLCodeMCodeNCodeOCodePCodeQCodeRCodeSCodeTCodeUCodeVCodeWCodeXCodeYCodeZCode1Code2Code3Code4Code5Code6Code7Code8Code9Code0CodeReturnEnterCodeEscapeCodeDeleteBackspaceCodeTabCodeSpacebarCodeHyphenMinusCodeEqualSignCodeLeftSquareBracketCodeRightSquareBracketCodeBackslash"
|
||||
_Code_name_2 = "CodeSemicolonCodeApostropheCodeGraveAccentCodeCommaCodeFullStopCodeSlashCodeCapsLockCodeF1CodeF2CodeF3CodeF4CodeF5CodeF6CodeF7CodeF8CodeF9CodeF10CodeF11CodeF12"
|
||||
_Code_name_3 = "CodePauseCodeInsertCodeHomeCodePageUpCodeDeleteForwardCodeEndCodePageDownCodeRightArrowCodeLeftArrowCodeDownArrowCodeUpArrowCodeKeypadNumLockCodeKeypadSlashCodeKeypadAsteriskCodeKeypadHyphenMinusCodeKeypadPlusSignCodeKeypadEnterCodeKeypad1CodeKeypad2CodeKeypad3CodeKeypad4CodeKeypad5CodeKeypad6CodeKeypad7CodeKeypad8CodeKeypad9CodeKeypad0CodeKeypadFullStop"
|
||||
_Code_name_4 = "CodeKeypadEqualSignCodeF13CodeF14CodeF15CodeF16CodeF17CodeF18CodeF19CodeF20CodeF21CodeF22CodeF23CodeF24"
|
||||
_Code_name_5 = "CodeHelp"
|
||||
_Code_name_6 = "CodeMuteCodeVolumeUpCodeVolumeDown"
|
||||
_Code_name_7 = "CodeLeftControlCodeLeftShiftCodeLeftAltCodeLeftGUICodeRightControlCodeRightShiftCodeRightAltCodeRightGUI"
|
||||
_Code_name_8 = "CodeCompose"
|
||||
)
|
||||
|
||||
var (
|
||||
_Code_index_0 = [...]uint8{0, 11}
|
||||
_Code_index_1 = [...]uint16{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 195, 205, 224, 231, 243, 258, 271, 292, 314, 327}
|
||||
_Code_index_2 = [...]uint8{0, 13, 27, 42, 51, 63, 72, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 145, 152, 159}
|
||||
_Code_index_3 = [...]uint16{0, 9, 19, 27, 37, 54, 61, 73, 87, 100, 113, 124, 141, 156, 174, 195, 213, 228, 239, 250, 261, 272, 283, 294, 305, 316, 327, 338, 356}
|
||||
_Code_index_4 = [...]uint8{0, 19, 26, 33, 40, 47, 54, 61, 68, 75, 82, 89, 96, 103}
|
||||
_Code_index_5 = [...]uint8{0, 8}
|
||||
_Code_index_6 = [...]uint8{0, 8, 20, 34}
|
||||
_Code_index_7 = [...]uint8{0, 15, 28, 39, 50, 66, 80, 92, 104}
|
||||
_Code_index_8 = [...]uint8{0, 11}
|
||||
)
|
||||
|
||||
func (i Code) String() string {
|
||||
switch {
|
||||
case i == 0:
|
||||
return _Code_name_0
|
||||
case 4 <= i && i <= 49:
|
||||
i -= 4
|
||||
return _Code_name_1[_Code_index_1[i]:_Code_index_1[i+1]]
|
||||
case 51 <= i && i <= 69:
|
||||
i -= 51
|
||||
return _Code_name_2[_Code_index_2[i]:_Code_index_2[i+1]]
|
||||
case 72 <= i && i <= 99:
|
||||
i -= 72
|
||||
return _Code_name_3[_Code_index_3[i]:_Code_index_3[i+1]]
|
||||
case 103 <= i && i <= 115:
|
||||
i -= 103
|
||||
return _Code_name_4[_Code_index_4[i]:_Code_index_4[i+1]]
|
||||
case i == 117:
|
||||
return _Code_name_5
|
||||
case 127 <= i && i <= 129:
|
||||
i -= 127
|
||||
return _Code_name_6[_Code_index_6[i]:_Code_index_6[i+1]]
|
||||
case 224 <= i && i <= 231:
|
||||
i -= 224
|
||||
return _Code_name_7[_Code_index_7[i]:_Code_index_7[i+1]]
|
||||
case i == 65536:
|
||||
return _Code_name_8
|
||||
default:
|
||||
return fmt.Sprintf("Code(%d)", i)
|
||||
}
|
||||
}
|
270
vendor/github.com/ebitengine/gomobile/event/key/key.go
generated
vendored
Normal file
270
vendor/github.com/ebitengine/gomobile/event/key/key.go
generated
vendored
Normal file
@ -0,0 +1,270 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate stringer -type=Code
|
||||
|
||||
// Package key defines an event for physical keyboard keys.
|
||||
//
|
||||
// On-screen software keyboards do not send key events.
|
||||
//
|
||||
// See the github.com/ebitengine/gomobile/app package for details on the event model.
|
||||
package key
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Event is a key event.
|
||||
type Event struct {
|
||||
// Rune is the meaning of the key event as determined by the
|
||||
// operating system. The mapping is determined by system-dependent
|
||||
// current layout, modifiers, lock-states, etc.
|
||||
//
|
||||
// If non-negative, it is a Unicode codepoint: pressing the 'a' key
|
||||
// generates different Runes 'a' or 'A' (but the same Code) depending on
|
||||
// the state of the shift key.
|
||||
//
|
||||
// If -1, the key does not generate a Unicode codepoint. To distinguish
|
||||
// them, look at Code.
|
||||
Rune rune
|
||||
|
||||
// Code is the identity of the physical key relative to a notional
|
||||
// "standard" keyboard, independent of current layout, modifiers,
|
||||
// lock-states, etc
|
||||
//
|
||||
// For standard key codes, its value matches USB HID key codes.
|
||||
// Compare its value to uint32-typed constants in this package, such
|
||||
// as CodeLeftShift and CodeEscape.
|
||||
//
|
||||
// Pressing the regular '2' key and number-pad '2' key (with Num-Lock)
|
||||
// generate different Codes (but the same Rune).
|
||||
Code Code
|
||||
|
||||
// Modifiers is a bitmask representing a set of modifier keys: ModShift,
|
||||
// ModAlt, etc.
|
||||
Modifiers Modifiers
|
||||
|
||||
// Direction is the direction of the key event: DirPress, DirRelease,
|
||||
// or DirNone (for key repeats).
|
||||
Direction Direction
|
||||
|
||||
// TODO: add a Device ID, for multiple input devices?
|
||||
// TODO: add a time.Time?
|
||||
}
|
||||
|
||||
func (e Event) String() string {
|
||||
if e.Rune >= 0 {
|
||||
return fmt.Sprintf("key.Event{%q (%v), %v, %v}", e.Rune, e.Code, e.Modifiers, e.Direction)
|
||||
}
|
||||
return fmt.Sprintf("key.Event{(%v), %v, %v}", e.Code, e.Modifiers, e.Direction)
|
||||
}
|
||||
|
||||
// Direction is the direction of the key event.
|
||||
type Direction uint8
|
||||
|
||||
const (
|
||||
DirNone Direction = 0
|
||||
DirPress Direction = 1
|
||||
DirRelease Direction = 2
|
||||
)
|
||||
|
||||
// Modifiers is a bitmask representing a set of modifier keys.
|
||||
type Modifiers uint32
|
||||
|
||||
const (
|
||||
ModShift Modifiers = 1 << 0
|
||||
ModControl Modifiers = 1 << 1
|
||||
ModAlt Modifiers = 1 << 2
|
||||
ModMeta Modifiers = 1 << 3 // called "Command" on OS X
|
||||
)
|
||||
|
||||
// Code is the identity of a key relative to a notional "standard" keyboard.
|
||||
type Code uint32
|
||||
|
||||
// Physical key codes.
|
||||
//
|
||||
// For standard key codes, its value matches USB HID key codes.
|
||||
// TODO: add missing codes.
|
||||
const (
|
||||
CodeUnknown Code = 0
|
||||
|
||||
CodeA Code = 4
|
||||
CodeB Code = 5
|
||||
CodeC Code = 6
|
||||
CodeD Code = 7
|
||||
CodeE Code = 8
|
||||
CodeF Code = 9
|
||||
CodeG Code = 10
|
||||
CodeH Code = 11
|
||||
CodeI Code = 12
|
||||
CodeJ Code = 13
|
||||
CodeK Code = 14
|
||||
CodeL Code = 15
|
||||
CodeM Code = 16
|
||||
CodeN Code = 17
|
||||
CodeO Code = 18
|
||||
CodeP Code = 19
|
||||
CodeQ Code = 20
|
||||
CodeR Code = 21
|
||||
CodeS Code = 22
|
||||
CodeT Code = 23
|
||||
CodeU Code = 24
|
||||
CodeV Code = 25
|
||||
CodeW Code = 26
|
||||
CodeX Code = 27
|
||||
CodeY Code = 28
|
||||
CodeZ Code = 29
|
||||
|
||||
Code1 Code = 30
|
||||
Code2 Code = 31
|
||||
Code3 Code = 32
|
||||
Code4 Code = 33
|
||||
Code5 Code = 34
|
||||
Code6 Code = 35
|
||||
Code7 Code = 36
|
||||
Code8 Code = 37
|
||||
Code9 Code = 38
|
||||
Code0 Code = 39
|
||||
|
||||
CodeReturnEnter Code = 40
|
||||
CodeEscape Code = 41
|
||||
CodeDeleteBackspace Code = 42
|
||||
CodeTab Code = 43
|
||||
CodeSpacebar Code = 44
|
||||
CodeHyphenMinus Code = 45 // -
|
||||
CodeEqualSign Code = 46 // =
|
||||
CodeLeftSquareBracket Code = 47 // [
|
||||
CodeRightSquareBracket Code = 48 // ]
|
||||
CodeBackslash Code = 49 // \
|
||||
CodeSemicolon Code = 51 // ;
|
||||
CodeApostrophe Code = 52 // '
|
||||
CodeGraveAccent Code = 53 // `
|
||||
CodeComma Code = 54 // ,
|
||||
CodeFullStop Code = 55 // .
|
||||
CodeSlash Code = 56 // /
|
||||
CodeCapsLock Code = 57
|
||||
|
||||
CodeF1 Code = 58
|
||||
CodeF2 Code = 59
|
||||
CodeF3 Code = 60
|
||||
CodeF4 Code = 61
|
||||
CodeF5 Code = 62
|
||||
CodeF6 Code = 63
|
||||
CodeF7 Code = 64
|
||||
CodeF8 Code = 65
|
||||
CodeF9 Code = 66
|
||||
CodeF10 Code = 67
|
||||
CodeF11 Code = 68
|
||||
CodeF12 Code = 69
|
||||
|
||||
CodePause Code = 72
|
||||
CodeInsert Code = 73
|
||||
CodeHome Code = 74
|
||||
CodePageUp Code = 75
|
||||
CodeDeleteForward Code = 76
|
||||
CodeEnd Code = 77
|
||||
CodePageDown Code = 78
|
||||
|
||||
CodeRightArrow Code = 79
|
||||
CodeLeftArrow Code = 80
|
||||
CodeDownArrow Code = 81
|
||||
CodeUpArrow Code = 82
|
||||
|
||||
CodeKeypadNumLock Code = 83
|
||||
CodeKeypadSlash Code = 84 // /
|
||||
CodeKeypadAsterisk Code = 85 // *
|
||||
CodeKeypadHyphenMinus Code = 86 // -
|
||||
CodeKeypadPlusSign Code = 87 // +
|
||||
CodeKeypadEnter Code = 88
|
||||
CodeKeypad1 Code = 89
|
||||
CodeKeypad2 Code = 90
|
||||
CodeKeypad3 Code = 91
|
||||
CodeKeypad4 Code = 92
|
||||
CodeKeypad5 Code = 93
|
||||
CodeKeypad6 Code = 94
|
||||
CodeKeypad7 Code = 95
|
||||
CodeKeypad8 Code = 96
|
||||
CodeKeypad9 Code = 97
|
||||
CodeKeypad0 Code = 98
|
||||
CodeKeypadFullStop Code = 99 // .
|
||||
CodeKeypadEqualSign Code = 103 // =
|
||||
|
||||
CodeF13 Code = 104
|
||||
CodeF14 Code = 105
|
||||
CodeF15 Code = 106
|
||||
CodeF16 Code = 107
|
||||
CodeF17 Code = 108
|
||||
CodeF18 Code = 109
|
||||
CodeF19 Code = 110
|
||||
CodeF20 Code = 111
|
||||
CodeF21 Code = 112
|
||||
CodeF22 Code = 113
|
||||
CodeF23 Code = 114
|
||||
CodeF24 Code = 115
|
||||
|
||||
CodeHelp Code = 117
|
||||
|
||||
CodeMute Code = 127
|
||||
CodeVolumeUp Code = 128
|
||||
CodeVolumeDown Code = 129
|
||||
|
||||
CodeLeftControl Code = 224
|
||||
CodeLeftShift Code = 225
|
||||
CodeLeftAlt Code = 226
|
||||
CodeLeftGUI Code = 227
|
||||
CodeRightControl Code = 228
|
||||
CodeRightShift Code = 229
|
||||
CodeRightAlt Code = 230
|
||||
CodeRightGUI Code = 231
|
||||
|
||||
// The following codes are not part of the standard USB HID Usage IDs for
|
||||
// keyboards. See http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
|
||||
//
|
||||
// Usage IDs are uint16s, so these non-standard values start at 0x10000.
|
||||
|
||||
// CodeCompose is the Code for a compose key, sometimes called a multi key,
|
||||
// used to input non-ASCII characters such as ñ being composed of n and ~.
|
||||
//
|
||||
// See https://en.wikipedia.org/wiki/Compose_key
|
||||
CodeCompose Code = 0x10000
|
||||
)
|
||||
|
||||
// TODO: Given we use runes outside the unicode space, should we provide a
|
||||
// printing function? Related: it's a little unfortunate that printing a
|
||||
// key.Event with %v gives not very readable output like:
|
||||
// {100 7 key.Modifiers() Press}
|
||||
|
||||
var mods = [...]struct {
|
||||
m Modifiers
|
||||
s string
|
||||
}{
|
||||
{ModShift, "Shift"},
|
||||
{ModControl, "Control"},
|
||||
{ModAlt, "Alt"},
|
||||
{ModMeta, "Meta"},
|
||||
}
|
||||
|
||||
func (m Modifiers) String() string {
|
||||
var match []string
|
||||
for _, mod := range mods {
|
||||
if mod.m&m != 0 {
|
||||
match = append(match, mod.s)
|
||||
}
|
||||
}
|
||||
return "key.Modifiers(" + strings.Join(match, "|") + ")"
|
||||
}
|
||||
|
||||
func (d Direction) String() string {
|
||||
switch d {
|
||||
case DirNone:
|
||||
return "None"
|
||||
case DirPress:
|
||||
return "Press"
|
||||
case DirRelease:
|
||||
return "Release"
|
||||
default:
|
||||
return fmt.Sprintf("key.Direction(%d)", d)
|
||||
}
|
||||
}
|
136
vendor/github.com/ebitengine/gomobile/event/lifecycle/lifecycle.go
generated
vendored
Normal file
136
vendor/github.com/ebitengine/gomobile/event/lifecycle/lifecycle.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package lifecycle defines an event for an app's lifecycle.
|
||||
//
|
||||
// The app lifecycle consists of moving back and forth between an ordered
|
||||
// sequence of stages. For example, being at a stage greater than or equal to
|
||||
// StageVisible means that the app is visible on the screen.
|
||||
//
|
||||
// A lifecycle event is a change from one stage to another, which crosses every
|
||||
// intermediate stage. For example, changing from StageAlive to StageFocused
|
||||
// implicitly crosses StageVisible.
|
||||
//
|
||||
// Crosses can be in a positive or negative direction. A positive crossing of
|
||||
// StageFocused means that the app has gained the focus. A negative crossing
|
||||
// means it has lost the focus.
|
||||
//
|
||||
// See the github.com/ebitengine/gomobile/app package for details on the event model.
|
||||
package lifecycle // import "github.com/ebitengine/gomobile/event/lifecycle"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Cross is whether a lifecycle stage was crossed.
|
||||
type Cross uint32
|
||||
|
||||
func (c Cross) String() string {
|
||||
switch c {
|
||||
case CrossOn:
|
||||
return "on"
|
||||
case CrossOff:
|
||||
return "off"
|
||||
}
|
||||
return "none"
|
||||
}
|
||||
|
||||
const (
|
||||
CrossNone Cross = 0
|
||||
CrossOn Cross = 1
|
||||
CrossOff Cross = 2
|
||||
)
|
||||
|
||||
// Event is a lifecycle change from an old stage to a new stage.
|
||||
type Event struct {
|
||||
From, To Stage
|
||||
|
||||
// DrawContext is the state used for painting, if any is valid.
|
||||
//
|
||||
// For OpenGL apps, a non-nil DrawContext is a gl.Context.
|
||||
//
|
||||
// TODO: make this an App method if we move away from an event channel?
|
||||
DrawContext interface{}
|
||||
}
|
||||
|
||||
func (e Event) String() string {
|
||||
return fmt.Sprintf("lifecycle.Event{From:%v, To:%v, DrawContext:%v}", e.From, e.To, e.DrawContext)
|
||||
}
|
||||
|
||||
// Crosses reports whether the transition from From to To crosses the stage s:
|
||||
// - It returns CrossOn if it does, and the lifecycle change is positive.
|
||||
// - It returns CrossOff if it does, and the lifecycle change is negative.
|
||||
// - Otherwise, it returns CrossNone.
|
||||
//
|
||||
// See the documentation for Stage for more discussion of positive and negative
|
||||
// crosses.
|
||||
func (e Event) Crosses(s Stage) Cross {
|
||||
switch {
|
||||
case e.From < s && e.To >= s:
|
||||
return CrossOn
|
||||
case e.From >= s && e.To < s:
|
||||
return CrossOff
|
||||
}
|
||||
return CrossNone
|
||||
}
|
||||
|
||||
// Stage is a stage in the app's lifecycle. The values are ordered, so that a
|
||||
// lifecycle change from stage From to stage To implicitly crosses every stage
|
||||
// in the range (min, max], exclusive on the low end and inclusive on the high
|
||||
// end, where min is the minimum of From and To, and max is the maximum.
|
||||
//
|
||||
// The documentation for individual stages talk about positive and negative
|
||||
// crosses. A positive lifecycle change is one where its From stage is less
|
||||
// than its To stage. Similarly, a negative lifecycle change is one where From
|
||||
// is greater than To. Thus, a positive lifecycle change crosses every stage in
|
||||
// the range (From, To] in increasing order, and a negative lifecycle change
|
||||
// crosses every stage in the range (To, From] in decreasing order.
|
||||
type Stage uint32
|
||||
|
||||
// TODO: how does iOS map to these stages? What do cross-platform mobile
|
||||
// abstractions do?
|
||||
|
||||
const (
|
||||
// StageDead is the zero stage. No lifecycle change crosses this stage,
|
||||
// but:
|
||||
// - A positive change from this stage is the very first lifecycle change.
|
||||
// - A negative change to this stage is the very last lifecycle change.
|
||||
StageDead Stage = iota
|
||||
|
||||
// StageAlive means that the app is alive.
|
||||
// - A positive cross means that the app has been created.
|
||||
// - A negative cross means that the app is being destroyed.
|
||||
// Each cross, either from or to StageDead, will occur only once.
|
||||
// On Android, these correspond to onCreate and onDestroy.
|
||||
StageAlive
|
||||
|
||||
// StageVisible means that the app window is visible.
|
||||
// - A positive cross means that the app window has become visible.
|
||||
// - A negative cross means that the app window has become invisible.
|
||||
// On Android, these correspond to onStart and onStop.
|
||||
// On Desktop, an app window can become invisible if e.g. it is minimized,
|
||||
// unmapped, or not on a visible workspace.
|
||||
StageVisible
|
||||
|
||||
// StageFocused means that the app window has the focus.
|
||||
// - A positive cross means that the app window has gained the focus.
|
||||
// - A negative cross means that the app window has lost the focus.
|
||||
// On Android, these correspond to onResume and onFreeze.
|
||||
StageFocused
|
||||
)
|
||||
|
||||
func (s Stage) String() string {
|
||||
switch s {
|
||||
case StageDead:
|
||||
return "StageDead"
|
||||
case StageAlive:
|
||||
return "StageAlive"
|
||||
case StageVisible:
|
||||
return "StageVisible"
|
||||
case StageFocused:
|
||||
return "StageFocused"
|
||||
default:
|
||||
return fmt.Sprintf("lifecycle.Stage(%d)", s)
|
||||
}
|
||||
}
|
24
vendor/github.com/ebitengine/gomobile/event/paint/paint.go
generated
vendored
Normal file
24
vendor/github.com/ebitengine/gomobile/event/paint/paint.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package paint defines an event for the app being ready to paint.
|
||||
//
|
||||
// See the github.com/ebitengine/gomobile/app package for details on the event model.
|
||||
package paint // import "github.com/ebitengine/gomobile/event/paint"
|
||||
|
||||
// Event indicates that the app is ready to paint the next frame of the GUI.
|
||||
//
|
||||
// A frame is completed by calling the App's Publish method.
|
||||
type Event struct {
|
||||
// External is true for paint events sent by the screen driver.
|
||||
//
|
||||
// An external event may be sent at any time in response to an
|
||||
// operating system event, for example the window opened, was
|
||||
// resized, or the screen memory was lost.
|
||||
//
|
||||
// Programs actively drawing to the screen as fast as vsync allows
|
||||
// should ignore external paint events to avoid a backlog of paint
|
||||
// events building up.
|
||||
External bool
|
||||
}
|
92
vendor/github.com/ebitengine/gomobile/event/size/size.go
generated
vendored
Normal file
92
vendor/github.com/ebitengine/gomobile/event/size/size.go
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package size defines an event for the dimensions, physical resolution and
|
||||
// orientation of the app's window.
|
||||
//
|
||||
// See the github.com/ebitengine/gomobile/app package for details on the event model.
|
||||
package size // import "github.com/ebitengine/gomobile/event/size"
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
"github.com/ebitengine/gomobile/geom"
|
||||
)
|
||||
|
||||
// Event holds the dimensions, physical resolution and orientation of the app's
|
||||
// window.
|
||||
type Event struct {
|
||||
// WidthPx and HeightPx are the window's dimensions in pixels.
|
||||
WidthPx, HeightPx int
|
||||
|
||||
// WidthPt and HeightPt are the window's physical dimensions in points
|
||||
// (1/72 of an inch).
|
||||
//
|
||||
// The values are based on PixelsPerPt and are therefore approximate, as
|
||||
// per the comment on PixelsPerPt.
|
||||
WidthPt, HeightPt geom.Pt
|
||||
|
||||
// PixelsPerPt is the window's physical resolution. It is the number of
|
||||
// pixels in a single geom.Pt, from the github.com/ebitengine/gomobile/geom package.
|
||||
//
|
||||
// There are a wide variety of pixel densities in existing phones and
|
||||
// tablets, so apps should be written to expect various non-integer
|
||||
// PixelsPerPt values. In general, work in geom.Pt.
|
||||
//
|
||||
// The value is approximate, in that the OS, drivers or hardware may report
|
||||
// approximate or quantized values. An N x N pixel square should be roughly
|
||||
// 1 square inch for N = int(PixelsPerPt * 72), although different square
|
||||
// lengths (in pixels) might be closer to 1 inch in practice. Nonetheless,
|
||||
// this PixelsPerPt value should be consistent with e.g. the ratio of
|
||||
// WidthPx to WidthPt.
|
||||
PixelsPerPt float32
|
||||
|
||||
// Orientation is the orientation of the device screen.
|
||||
Orientation Orientation
|
||||
}
|
||||
|
||||
// Size returns the window's size in pixels, at the time this size event was
|
||||
// sent.
|
||||
func (e Event) Size() image.Point {
|
||||
return image.Point{e.WidthPx, e.HeightPx}
|
||||
}
|
||||
|
||||
// Bounds returns the window's bounds in pixels, at the time this size event
|
||||
// was sent.
|
||||
//
|
||||
// The top-left pixel is always (0, 0). The bottom-right pixel is given by the
|
||||
// width and height.
|
||||
func (e Event) Bounds() image.Rectangle {
|
||||
return image.Rectangle{Max: image.Point{e.WidthPx, e.HeightPx}}
|
||||
}
|
||||
|
||||
// Orientation is the orientation of the device screen.
|
||||
type Orientation int
|
||||
|
||||
const (
|
||||
// OrientationUnknown means device orientation cannot be determined.
|
||||
//
|
||||
// Equivalent on Android to Configuration.ORIENTATION_UNKNOWN
|
||||
// and on iOS to:
|
||||
// UIDeviceOrientationUnknown
|
||||
// UIDeviceOrientationFaceUp
|
||||
// UIDeviceOrientationFaceDown
|
||||
OrientationUnknown Orientation = iota
|
||||
|
||||
// OrientationPortrait is a device oriented so it is tall and thin.
|
||||
//
|
||||
// Equivalent on Android to Configuration.ORIENTATION_PORTRAIT
|
||||
// and on iOS to:
|
||||
// UIDeviceOrientationPortrait
|
||||
// UIDeviceOrientationPortraitUpsideDown
|
||||
OrientationPortrait
|
||||
|
||||
// OrientationLandscape is a device oriented so it is short and wide.
|
||||
//
|
||||
// Equivalent on Android to Configuration.ORIENTATION_LANDSCAPE
|
||||
// and on iOS to:
|
||||
// UIDeviceOrientationLandscapeLeft
|
||||
// UIDeviceOrientationLandscapeRight
|
||||
OrientationLandscape
|
||||
)
|
72
vendor/github.com/ebitengine/gomobile/event/touch/touch.go
generated
vendored
Normal file
72
vendor/github.com/ebitengine/gomobile/event/touch/touch.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package touch defines an event for touch input.
|
||||
//
|
||||
// See the github.com/ebitengine/gomobile/app package for details on the event model.
|
||||
package touch // import "github.com/ebitengine/gomobile/event/touch"
|
||||
|
||||
// The best source on android input events is the NDK: include/android/input.h
|
||||
//
|
||||
// iOS event handling guide:
|
||||
// https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Event is a touch event.
|
||||
type Event struct {
|
||||
// X and Y are the touch location, in pixels.
|
||||
X, Y float32
|
||||
|
||||
// Sequence is the sequence number. The same number is shared by all events
|
||||
// in a sequence. A sequence begins with a single TypeBegin, is followed by
|
||||
// zero or more TypeMoves, and ends with a single TypeEnd. A Sequence
|
||||
// distinguishes concurrent sequences but its value is subsequently reused.
|
||||
Sequence Sequence
|
||||
|
||||
// Type is the touch type.
|
||||
Type Type
|
||||
}
|
||||
|
||||
// Sequence identifies a sequence of touch events.
|
||||
type Sequence int64
|
||||
|
||||
// Type describes the type of a touch event.
|
||||
type Type byte
|
||||
|
||||
const (
|
||||
// TypeBegin is a user first touching the device.
|
||||
//
|
||||
// On Android, this is a AMOTION_EVENT_ACTION_DOWN.
|
||||
// On iOS, this is a call to touchesBegan.
|
||||
TypeBegin Type = iota
|
||||
|
||||
// TypeMove is a user dragging across the device.
|
||||
//
|
||||
// A TypeMove is delivered between a TypeBegin and TypeEnd.
|
||||
//
|
||||
// On Android, this is a AMOTION_EVENT_ACTION_MOVE.
|
||||
// On iOS, this is a call to touchesMoved.
|
||||
TypeMove
|
||||
|
||||
// TypeEnd is a user no longer touching the device.
|
||||
//
|
||||
// On Android, this is a AMOTION_EVENT_ACTION_UP.
|
||||
// On iOS, this is a call to touchesEnded.
|
||||
TypeEnd
|
||||
)
|
||||
|
||||
func (t Type) String() string {
|
||||
switch t {
|
||||
case TypeBegin:
|
||||
return "begin"
|
||||
case TypeMove:
|
||||
return "move"
|
||||
case TypeEnd:
|
||||
return "end"
|
||||
}
|
||||
return fmt.Sprintf("touch.Type(%d)", t)
|
||||
}
|
102
vendor/github.com/ebitengine/gomobile/geom/geom.go
generated
vendored
Normal file
102
vendor/github.com/ebitengine/gomobile/geom/geom.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package geom defines a two-dimensional coordinate system.
|
||||
|
||||
The coordinate system is based on an left-handed Cartesian plane.
|
||||
That is, X increases to the right and Y increases down. For (x,y),
|
||||
|
||||
(0,0) → (1,0)
|
||||
↓ ↘
|
||||
(0,1) (1,1)
|
||||
|
||||
The display window places the origin (0, 0) in the upper-left corner of
|
||||
the screen. Positions on the plane are measured in typographic points,
|
||||
1/72 of an inch, which is represented by the Pt type.
|
||||
|
||||
Any interface that draws to the screen using types from the geom package
|
||||
scales the number of pixels to maintain a Pt as 1/72 of an inch.
|
||||
*/
|
||||
package geom // import "github.com/ebitengine/gomobile/geom"
|
||||
|
||||
/*
|
||||
Notes on the various underlying coordinate systems.
|
||||
|
||||
Both Android and iOS (UIKit) use upper-left-origin coordinate systems
|
||||
with for events, however they have different units.
|
||||
|
||||
UIKit measures distance in points. A point is a single-pixel on a
|
||||
pre-Retina display. UIKit maintains a scale factor that to turn points
|
||||
into pixels. On current retina devices, the scale factor is 2.0.
|
||||
|
||||
A UIKit point does not correspond to a fixed physical distance, as the
|
||||
iPhone has a 163 DPI/PPI (326 PPI retina) display, and the iPad has a
|
||||
132 PPI (264 retina) display. Points are 32-bit floats.
|
||||
|
||||
Even though point is the official UIKit term, they are commonly called
|
||||
pixels. Indeed, the units were equivalent until the retina display was
|
||||
introduced.
|
||||
|
||||
N.b. as a UIKit point is unrelated to a typographic point, it is not
|
||||
related to this packages's Pt and Point types.
|
||||
|
||||
More details about iOS drawing:
|
||||
|
||||
https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/GraphicsDrawingOverview/GraphicsDrawingOverview.html
|
||||
|
||||
Android uses pixels. Sub-pixel precision is possible, so pixels are
|
||||
represented as 32-bit floats. The ACONFIGURATION_DENSITY enum provides
|
||||
the screen DPI/PPI, which varies frequently between devices.
|
||||
|
||||
It would be tempting to adopt the pixel, given the clear pixel/DPI split
|
||||
in the core android events API. However, the plot thickens:
|
||||
|
||||
http://developer.android.com/training/multiscreen/screendensities.html
|
||||
|
||||
Android promotes the notion of a density-independent pixel in many of
|
||||
their interfaces, often prefixed by "dp". 1dp is a real physical length,
|
||||
as "independent" means it is assumed to be 1/160th of an inch and is
|
||||
adjusted for the current screen.
|
||||
|
||||
In addition, android has a scale-indepdendent pixel used for expressing
|
||||
a user's preferred text size. The user text size preference is a useful
|
||||
notion not yet expressed in the geom package.
|
||||
|
||||
For the sake of clarity when working across platforms, the geom package
|
||||
tries to put distance between it and the word pixel.
|
||||
*/
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Pt is a length.
|
||||
//
|
||||
// The unit Pt is a typographical point, 1/72 of an inch (0.3527 mm).
|
||||
//
|
||||
// It can be converted to a length in current device pixels by
|
||||
// multiplying with PixelsPerPt after app initialization is complete.
|
||||
type Pt float32
|
||||
|
||||
// Px converts the length to current device pixels.
|
||||
func (p Pt) Px(pixelsPerPt float32) float32 { return float32(p) * pixelsPerPt }
|
||||
|
||||
// String returns a string representation of p like "3.2pt".
|
||||
func (p Pt) String() string { return fmt.Sprintf("%.2fpt", p) }
|
||||
|
||||
// Point is a point in a two-dimensional plane.
|
||||
type Point struct {
|
||||
X, Y Pt
|
||||
}
|
||||
|
||||
// String returns a string representation of p like "(1.2,3.4)".
|
||||
func (p Point) String() string { return fmt.Sprintf("(%.2f,%.2f)", p.X, p.Y) }
|
||||
|
||||
// A Rectangle is region of points.
|
||||
// The top-left point is Min, and the bottom-right point is Max.
|
||||
type Rectangle struct {
|
||||
Min, Max Point
|
||||
}
|
||||
|
||||
// String returns a string representation of r like "(3,4)-(6,5)".
|
||||
func (r Rectangle) String() string { return r.Min.String() + "-" + r.Max.String() }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user