func TestMathAcosh(t *testing.T) { // This is just an interface to Go's function, so just a quick simple test ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) val := 1.12 ret := mm.math_Acosh(runtime.Number(val)) exp := math.Acosh(val) if ret.Float() != exp { t.Errorf("expected %f, got %f", exp, ret.Float()) } }
//AcosH returns the inverse hyperbolic cosine of x func AcosH(number float64) (float64, error) { if number < 1 { return 0.0, errors.New("#NUM! - Occurred because the supplied number argument is less than 1") } if math.IsNaN(number) { return 0.0, errors.New("#VALUE! - Occurred because the supplied number argument is non-numeric") } return math.Acosh(number), nil }
// Chebyshev biquad (2-poles) recursive coefficients // Adapted from The Scientist and Engineer's Guide to Digital Signal Processing, Steven W. Smith // poleIndex = [0, poleCount) // percentRipple in the pass band can range from 0 for a butterworth to about 0.29. Something like 0.005 is a good trade-off. func chebyshevBiquad(freq, percentRipple float64, poleIndex, poleCount int, highpass bool) (stageAs, stageBs []float64) { // We start off by designing a low-pass filter with unity cut-off frequency // Location of pole on unit circle, real and imaginary parts // The maximally flat butterworth filter positions the poles so that // they form a semi-circle on the left side of the s-plane (sigma < 0) // The half offset keeps the poles evenly spaced and off of the sigma=0 line // s-plane s = sigma + i * omega = poleR + i * poleI poleI, poleR := math.Sincos((float64(poleIndex) + 0.5) * math.Pi / float64(poleCount)) poleR = -poleR // The chebyshev filter uses an ellipse to move all of the poles closer to the sigma=0 line // This causes pass-band ripple and sharpens the drop off // Warp coordinates from being on a circle to an ellipse if percentRipple != 0.0 { e := math.Sqrt(1/((1-percentRipple)*(1-percentRipple)) - 1) v := math.Asinh(1/e) / float64(poleCount) k := math.Acosh(1/e) / float64(poleCount) k = math.Cosh(k) poleR = poleR * math.Sinh(v) / k poleI = poleI * math.Cosh(v) / k } // bilinear s-domain to z-domain transformation t := 2 * math.Tan(0.5) w := 2 * math.Pi * freq m := poleR*poleR + poleI*poleI d := 4 - 4*poleR*t + m*t*t x0 := t * t / d x1 := 2 * t * t / d x2 := t * t / d y1 := (8 - 2*m*t*t) / d y2 := (-4 - 4*poleR*t - m*t*t) / d // We now have the coefficients of a low-pass filter with a cutoff frequency of 1 (2 times the nyquist)... // We must now apply our desired frequency and convert to a high-pass filter if necessary // as with the bilinear tranform, these are the results of a substitution in the transfer function... var k float64 if highpass { k = -math.Cos(w/2+0.5) / math.Cos(w/2-0.5) } else { k = math.Sin(0.5-w/2) / math.Sin(0.5+w/2) } d = 1 + (y1*k - y2*k*k) a0 := (x0 - x1*k + x2*k*k) / d a1 := (-2*x0*k + x1 + (x1*k*k - 2*x2*k)) / d a2 := (x0*k*k - x1*k + x2) / d b1 := (2*k + y1 + y1*k*k - 2*y2*k) / d b2 := (-k*k - y1*k + y2) / d if highpass { a1, b1 = -a1, -b1 } // we now have the desired coefficients of our low/high pass filter with the desired cutoff frequency // however, the gain has not been normalized, if that is desired... stageAs = []float64{a0, a1, a2} stageBs = []float64{0, b1, b2} return }
// float32 version of math.Acoshf func Acosh(x float32) float32 { return float32(math.Acosh(float64(x))) }
func (m *MathMod) math_Acosh(args ...runtime.Val) runtime.Val { runtime.ExpectAtLeastNArgs(1, args) return runtime.Number(math.Acosh(args[0].Float())) }