goscript 0.0.34 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/analysis.go +28 -20
- package/compiler/analysis_test.go +14 -0
- package/compiler/assignment.go +19 -7
- package/compiler/compiler.go +15 -99
- package/compiler/composite-lit.go +60 -17
- package/compiler/decl.go +1 -1
- package/compiler/expr-call.go +233 -35
- package/compiler/expr-selector.go +28 -2
- package/compiler/expr.go +13 -37
- package/compiler/lit.go +111 -2
- package/compiler/primitive.go +6 -6
- package/compiler/protobuf.go +0 -5
- package/compiler/sanitize.go +101 -0
- package/compiler/spec-struct.go +41 -8
- package/compiler/spec-value.go +29 -18
- package/compiler/stmt-assign.go +22 -1
- package/compiler/stmt.go +26 -9
- package/compiler/type.go +3 -3
- package/dist/gs/builtin/builtin.d.ts +3 -2
- package/dist/gs/builtin/builtin.js +2 -1
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +7 -1
- package/dist/gs/builtin/slice.js +112 -22
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.d.ts +13 -0
- package/dist/gs/github.com/pkg/errors/errors.js +232 -0
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/go113.d.ts +4 -0
- package/dist/gs/github.com/pkg/errors/go113.js +34 -0
- package/dist/gs/github.com/pkg/errors/go113.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/index.d.ts +3 -0
- package/dist/gs/github.com/pkg/errors/index.js +4 -0
- package/dist/gs/github.com/pkg/errors/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/stack.d.ts +32 -0
- package/dist/gs/github.com/pkg/errors/stack.js +111 -0
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -0
- package/dist/gs/maps/index.d.ts +2 -2
- package/dist/gs/maps/index.js +2 -2
- package/dist/gs/maps/index.js.map +1 -1
- package/dist/gs/maps/iter.d.ts +7 -0
- package/dist/gs/maps/iter.js +57 -0
- package/dist/gs/maps/iter.js.map +1 -0
- package/dist/gs/maps/maps.d.ts +7 -0
- package/dist/gs/maps/maps.js +67 -0
- package/dist/gs/maps/maps.js.map +1 -0
- package/dist/gs/math/abs.gs.d.ts +1 -0
- package/dist/gs/math/abs.gs.js +10 -0
- package/dist/gs/math/abs.gs.js.map +1 -0
- package/dist/gs/math/acosh.gs.d.ts +2 -0
- package/dist/gs/math/acosh.gs.js +14 -0
- package/dist/gs/math/acosh.gs.js.map +1 -0
- package/dist/gs/math/asin.gs.d.ts +4 -0
- package/dist/gs/math/asin.gs.js +24 -0
- package/dist/gs/math/asin.gs.js.map +1 -0
- package/dist/gs/math/asinh.gs.d.ts +2 -0
- package/dist/gs/math/asinh.gs.js +14 -0
- package/dist/gs/math/asinh.gs.js.map +1 -0
- package/dist/gs/math/atan.gs.d.ts +4 -0
- package/dist/gs/math/atan.gs.js +22 -0
- package/dist/gs/math/atan.gs.js.map +1 -0
- package/dist/gs/math/atan2.gs.d.ts +2 -0
- package/dist/gs/math/atan2.gs.js +30 -0
- package/dist/gs/math/atan2.gs.js.map +1 -0
- package/dist/gs/math/atanh.gs.d.ts +2 -0
- package/dist/gs/math/atanh.gs.js +16 -0
- package/dist/gs/math/atanh.gs.js.map +1 -0
- package/dist/gs/math/bits.gs.d.ts +5 -0
- package/dist/gs/math/bits.gs.js +46 -0
- package/dist/gs/math/bits.gs.js.map +1 -0
- package/dist/gs/math/cbrt.gs.d.ts +2 -0
- package/dist/gs/math/cbrt.gs.js +14 -0
- package/dist/gs/math/cbrt.gs.js.map +1 -0
- package/dist/gs/math/const.gs.d.ts +30 -0
- package/dist/gs/math/const.gs.js +61 -0
- package/dist/gs/math/const.gs.js.map +1 -0
- package/dist/gs/math/copysign.gs.d.ts +1 -0
- package/dist/gs/math/copysign.gs.js +20 -0
- package/dist/gs/math/copysign.gs.js.map +1 -0
- package/dist/gs/math/dim.gs.d.ts +5 -0
- package/dist/gs/math/dim.gs.js +69 -0
- package/dist/gs/math/dim.gs.js.map +1 -0
- package/dist/gs/math/erf.gs.d.ts +4 -0
- package/dist/gs/math/erf.gs.js +336 -0
- package/dist/gs/math/erf.gs.js.map +1 -0
- package/dist/gs/math/erfinv.gs.d.ts +2 -0
- package/dist/gs/math/erfinv.gs.js +118 -0
- package/dist/gs/math/erfinv.gs.js.map +1 -0
- package/dist/gs/math/exp.gs.d.ts +5 -0
- package/dist/gs/math/exp.gs.js +30 -0
- package/dist/gs/math/exp.gs.js.map +1 -0
- package/dist/gs/math/expm1.gs.d.ts +2 -0
- package/dist/gs/math/expm1.gs.js +17 -0
- package/dist/gs/math/expm1.gs.js.map +1 -0
- package/dist/gs/math/floor.gs.d.ts +8 -0
- package/dist/gs/math/floor.gs.js +75 -0
- package/dist/gs/math/floor.gs.js.map +1 -0
- package/dist/gs/math/fma.gs.d.ts +1 -0
- package/dist/gs/math/fma.gs.js +8 -0
- package/dist/gs/math/fma.gs.js.map +1 -0
- package/dist/gs/math/frexp.gs.d.ts +2 -0
- package/dist/gs/math/frexp.gs.js +28 -0
- package/dist/gs/math/frexp.gs.js.map +1 -0
- package/dist/gs/math/gamma.gs.d.ts +3 -0
- package/dist/gs/math/gamma.gs.js +149 -0
- package/dist/gs/math/gamma.gs.js.map +1 -0
- package/dist/gs/math/hypot.gs.d.ts +2 -0
- package/dist/gs/math/hypot.gs.js +16 -0
- package/dist/gs/math/hypot.gs.js.map +1 -0
- package/dist/gs/math/index.d.ts +44 -0
- package/dist/gs/math/index.js +45 -0
- package/dist/gs/math/index.js.map +1 -0
- package/dist/gs/math/j0.gs.d.ts +4 -0
- package/dist/gs/math/j0.gs.js +228 -0
- package/dist/gs/math/j0.gs.js.map +1 -0
- package/dist/gs/math/j1.gs.d.ts +4 -0
- package/dist/gs/math/j1.gs.js +211 -0
- package/dist/gs/math/j1.gs.js.map +1 -0
- package/dist/gs/math/jn.gs.d.ts +2 -0
- package/dist/gs/math/jn.gs.js +412 -0
- package/dist/gs/math/jn.gs.js.map +1 -0
- package/dist/gs/math/ldexp.gs.d.ts +2 -0
- package/dist/gs/math/ldexp.gs.js +20 -0
- package/dist/gs/math/ldexp.gs.js.map +1 -0
- package/dist/gs/math/lgamma.gs.d.ts +2 -0
- package/dist/gs/math/lgamma.gs.js +243 -0
- package/dist/gs/math/lgamma.gs.js.map +1 -0
- package/dist/gs/math/log.gs.d.ts +2 -0
- package/dist/gs/math/log.gs.js +16 -0
- package/dist/gs/math/log.gs.js.map +1 -0
- package/dist/gs/math/log10.gs.d.ts +4 -0
- package/dist/gs/math/log10.gs.js +17 -0
- package/dist/gs/math/log10.gs.js.map +1 -0
- package/dist/gs/math/log1p.gs.d.ts +2 -0
- package/dist/gs/math/log1p.gs.js +17 -0
- package/dist/gs/math/log1p.gs.js.map +1 -0
- package/dist/gs/math/logb.gs.d.ts +3 -0
- package/dist/gs/math/logb.gs.js +43 -0
- package/dist/gs/math/logb.gs.js.map +1 -0
- package/dist/gs/math/mod.gs.d.ts +2 -0
- package/dist/gs/math/mod.gs.js +26 -0
- package/dist/gs/math/mod.gs.js.map +1 -0
- package/dist/gs/math/modf.gs.d.ts +2 -0
- package/dist/gs/math/modf.gs.js +24 -0
- package/dist/gs/math/modf.gs.js.map +1 -0
- package/dist/gs/math/nextafter.gs.d.ts +2 -0
- package/dist/gs/math/nextafter.gs.js +66 -0
- package/dist/gs/math/nextafter.gs.js.map +1 -0
- package/dist/gs/math/pow.gs.d.ts +3 -0
- package/dist/gs/math/pow.gs.js +40 -0
- package/dist/gs/math/pow.gs.js.map +1 -0
- package/dist/gs/math/pow10.gs.d.ts +1 -0
- package/dist/gs/math/pow10.gs.js +14 -0
- package/dist/gs/math/pow10.gs.js.map +1 -0
- package/dist/gs/math/remainder.gs.d.ts +2 -0
- package/dist/gs/math/remainder.gs.js +25 -0
- package/dist/gs/math/remainder.gs.js.map +1 -0
- package/dist/gs/math/signbit.gs.d.ts +1 -0
- package/dist/gs/math/signbit.gs.js +5 -0
- package/dist/gs/math/signbit.gs.js.map +1 -0
- package/dist/gs/math/sin.gs.d.ts +4 -0
- package/dist/gs/math/sin.gs.js +29 -0
- package/dist/gs/math/sin.gs.js.map +1 -0
- package/dist/gs/math/sincos.gs.d.ts +1 -0
- package/dist/gs/math/sincos.gs.js +11 -0
- package/dist/gs/math/sincos.gs.js.map +1 -0
- package/dist/gs/math/sinh.gs.d.ts +4 -0
- package/dist/gs/math/sinh.gs.js +27 -0
- package/dist/gs/math/sinh.gs.js.map +1 -0
- package/dist/gs/math/sqrt.gs.d.ts +2 -0
- package/dist/gs/math/sqrt.gs.js +15 -0
- package/dist/gs/math/sqrt.gs.js.map +1 -0
- package/dist/gs/math/tan.gs.d.ts +2 -0
- package/dist/gs/math/tan.gs.js +17 -0
- package/dist/gs/math/tan.gs.js.map +1 -0
- package/dist/gs/math/tanh.gs.d.ts +2 -0
- package/dist/gs/math/tanh.gs.js +17 -0
- package/dist/gs/math/tanh.gs.js.map +1 -0
- package/dist/gs/math/trig_reduce.gs.d.ts +1 -0
- package/dist/gs/math/trig_reduce.gs.js +62 -0
- package/dist/gs/math/trig_reduce.gs.js.map +1 -0
- package/dist/gs/math/unsafe.gs.d.ts +4 -0
- package/dist/gs/math/unsafe.gs.js +47 -0
- package/dist/gs/math/unsafe.gs.js.map +1 -0
- package/dist/gs/strconv/atob.gs.d.ts +4 -0
- package/dist/gs/strconv/atob.gs.js +42 -0
- package/dist/gs/strconv/atob.gs.js.map +1 -0
- package/dist/gs/strconv/atof.gs.d.ts +2 -0
- package/dist/gs/strconv/atof.gs.js +51 -0
- package/dist/gs/strconv/atof.gs.js.map +1 -0
- package/dist/gs/strconv/atoi.gs.d.ts +33 -0
- package/dist/gs/strconv/atoi.gs.js +200 -0
- package/dist/gs/strconv/atoi.gs.js.map +1 -0
- package/dist/gs/strconv/doc.gs.d.ts +1 -0
- package/dist/gs/strconv/doc.gs.js +2 -0
- package/dist/gs/strconv/doc.gs.js.map +1 -0
- package/dist/gs/strconv/ftoa.gs.d.ts +3 -0
- package/dist/gs/strconv/ftoa.gs.js +58 -0
- package/dist/gs/strconv/ftoa.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +6 -0
- package/dist/gs/strconv/index.js +7 -0
- package/dist/gs/strconv/index.js.map +1 -0
- package/dist/gs/strconv/itoa.gs.d.ts +6 -0
- package/dist/gs/strconv/itoa.gs.js +37 -0
- package/dist/gs/strconv/itoa.gs.js.map +1 -0
- package/dist/gs/strconv/quote.gs.d.ts +19 -0
- package/dist/gs/strconv/quote.gs.js +217 -0
- package/dist/gs/strconv/quote.gs.js.map +1 -0
- package/dist/gs/strings/index.d.ts +3 -0
- package/dist/gs/strings/index.js +4 -0
- package/dist/gs/strings/index.js.map +1 -1
- package/dist/gs/strings/replace.d.ts +0 -74
- package/dist/gs/strings/replace.js +6 -204
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/search.d.ts +0 -1
- package/dist/gs/strings/search.js +0 -21
- package/dist/gs/strings/search.js.map +1 -1
- package/dist/gs/sync/atomic/doc.gs.d.ts +28 -0
- package/dist/gs/sync/atomic/doc.gs.js +265 -0
- package/dist/gs/sync/atomic/doc.gs.js.map +1 -0
- package/dist/gs/sync/atomic/doc_64.gs.d.ts +15 -0
- package/dist/gs/sync/atomic/doc_64.gs.js +165 -0
- package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -0
- package/dist/gs/sync/atomic/index.d.ts +4 -0
- package/dist/gs/sync/atomic/index.js +5 -0
- package/dist/gs/sync/atomic/index.js.map +1 -0
- package/dist/gs/sync/atomic/type.gs.d.ts +130 -0
- package/dist/gs/sync/atomic/type.gs.js +433 -0
- package/dist/gs/sync/atomic/type.gs.js.map +1 -0
- package/dist/gs/sync/atomic/value.gs.d.ts +19 -0
- package/dist/gs/sync/atomic/value.gs.js +116 -0
- package/dist/gs/sync/atomic/value.gs.js.map +1 -0
- package/dist/gs/unsafe/unsafe.d.ts +1 -0
- package/dist/gs/unsafe/unsafe.js +5 -0
- package/dist/gs/unsafe/unsafe.js.map +1 -1
- package/gs/builtin/builtin.ts +9 -7
- package/gs/builtin/map.ts +5 -1
- package/gs/builtin/slice.ts +152 -24
- package/gs/github.com/pkg/errors/errors.ts +307 -0
- package/gs/github.com/pkg/errors/go113.ts +39 -0
- package/gs/github.com/pkg/errors/index.ts +3 -0
- package/gs/github.com/pkg/errors/stack.ts +127 -0
- package/gs/maps/index.ts +2 -2
- package/gs/maps/iter.ts +67 -0
- package/gs/maps/maps.ts +89 -0
- package/gs/math/TODO.md +156 -0
- package/gs/math/abs.gs.test.ts +29 -0
- package/gs/math/abs.gs.ts +13 -0
- package/gs/math/acosh.gs.test.ts +39 -0
- package/gs/math/acosh.gs.ts +21 -0
- package/gs/math/asin.gs.test.ts +66 -0
- package/gs/math/asin.gs.ts +27 -0
- package/gs/math/asinh.gs.test.ts +37 -0
- package/gs/math/asinh.gs.ts +21 -0
- package/gs/math/atan.gs.test.ts +49 -0
- package/gs/math/atan.gs.ts +27 -0
- package/gs/math/atan2.gs.test.ts +55 -0
- package/gs/math/atan2.gs.ts +37 -0
- package/gs/math/atanh.gs.test.ts +47 -0
- package/gs/math/atanh.gs.ts +21 -0
- package/gs/math/bits.gs.test.ts +88 -0
- package/gs/math/bits.gs.ts +61 -0
- package/gs/math/cbrt.gs.test.ts +57 -0
- package/gs/math/cbrt.gs.ts +20 -0
- package/gs/math/const.gs.test.ts +54 -0
- package/gs/math/const.gs.ts +93 -0
- package/gs/math/copysign.gs.test.ts +44 -0
- package/gs/math/copysign.gs.ts +27 -0
- package/gs/math/dim.gs.test.ts +102 -0
- package/gs/math/dim.gs.ts +84 -0
- package/gs/math/erf.gs.test.ts +92 -0
- package/gs/math/erf.gs.ts +409 -0
- package/gs/math/erfinv.gs.test.ts +104 -0
- package/gs/math/erfinv.gs.ts +169 -0
- package/gs/math/exp.gs.test.ts +82 -0
- package/gs/math/exp.gs.ts +39 -0
- package/gs/math/expm1.gs.test.ts +48 -0
- package/gs/math/expm1.gs.ts +23 -0
- package/gs/math/floor.gs.test.ts +146 -0
- package/gs/math/floor.gs.ts +88 -0
- package/gs/math/fma.gs.test.ts +83 -0
- package/gs/math/fma.gs.ts +7 -0
- package/gs/math/frexp.gs.test.ts +146 -0
- package/gs/math/frexp.gs.ts +37 -0
- package/gs/math/gamma.gs.test.ts +66 -0
- package/gs/math/gamma.gs.ts +158 -0
- package/gs/math/hypot.gs.test.ts +73 -0
- package/gs/math/hypot.gs.ts +23 -0
- package/gs/math/index.ts +44 -0
- package/gs/math/j0.gs.test.ts +74 -0
- package/gs/math/j0.gs.ts +257 -0
- package/gs/math/j1.gs.test.ts +81 -0
- package/gs/math/j1.gs.ts +231 -0
- package/gs/math/jn.gs.test.ts +133 -0
- package/gs/math/jn.gs.ts +447 -0
- package/gs/math/ldexp.gs.test.ts +128 -0
- package/gs/math/ldexp.gs.ts +28 -0
- package/gs/math/lgamma.gs.test.ts +102 -0
- package/gs/math/lgamma.gs.ts +251 -0
- package/gs/math/log.gs.test.ts +40 -0
- package/gs/math/log.gs.ts +21 -0
- package/gs/math/log10.gs.test.ts +80 -0
- package/gs/math/log10.gs.ts +25 -0
- package/gs/math/log1p.gs.test.ts +55 -0
- package/gs/math/log1p.gs.ts +24 -0
- package/gs/math/logb.gs.test.ts +87 -0
- package/gs/math/logb.gs.ts +54 -0
- package/gs/math/mod.gs.test.ts +64 -0
- package/gs/math/mod.gs.ts +36 -0
- package/gs/math/modf.gs.test.ts +80 -0
- package/gs/math/modf.gs.ts +32 -0
- package/gs/math/nextafter.gs.test.ts +107 -0
- package/gs/math/nextafter.gs.ts +71 -0
- package/gs/math/pow.gs.test.ts +103 -0
- package/gs/math/pow.gs.ts +55 -0
- package/gs/math/pow10.gs.test.ts +58 -0
- package/gs/math/pow10.gs.ts +19 -0
- package/gs/math/remainder.gs.test.ts +70 -0
- package/gs/math/remainder.gs.ts +33 -0
- package/gs/math/signbit.gs.test.ts +33 -0
- package/gs/math/signbit.gs.ts +8 -0
- package/gs/math/sin.gs.test.ts +83 -0
- package/gs/math/sin.gs.ts +38 -0
- package/gs/math/sincos.gs.test.ts +91 -0
- package/gs/math/sincos.gs.ts +15 -0
- package/gs/math/sinh.gs.test.ts +66 -0
- package/gs/math/sinh.gs.ts +34 -0
- package/gs/math/sqrt.gs.test.ts +49 -0
- package/gs/math/sqrt.gs.ts +20 -0
- package/gs/math/tan.gs.test.ts +50 -0
- package/gs/math/tan.gs.ts +23 -0
- package/gs/math/tanh.gs.test.ts +52 -0
- package/gs/math/tanh.gs.ts +23 -0
- package/gs/math/trig_reduce.gs.ts +66 -0
- package/gs/math/unsafe.gs.ts +52 -0
- package/gs/strconv/atob.gs.ts +45 -0
- package/gs/strconv/atof.gs.ts +60 -0
- package/gs/strconv/atoi.gs.ts +243 -0
- package/gs/strconv/doc.gs.ts +2 -0
- package/gs/strconv/ftoa.gs.ts +66 -0
- package/gs/strconv/index.ts +6 -0
- package/gs/strconv/itoa.gs.ts +41 -0
- package/gs/strconv/quote.gs.ts +245 -0
- package/gs/strings/index.ts +4 -0
- package/gs/strings/replace.ts +9 -237
- package/gs/strings/search.ts +0 -28
- package/gs/sync/atomic/doc.gs.ts +276 -0
- package/gs/sync/atomic/doc_64.gs.ts +168 -0
- package/gs/sync/atomic/index.ts +4 -0
- package/gs/sync/atomic/type.gs.ts +596 -0
- package/gs/sync/atomic/value.gs.ts +158 -0
- package/gs/unsafe/unsafe.ts +6 -0
- package/package.json +1 -1
- package/gs/maps/iter.gs.ts +0 -71
- package/gs/maps/maps.gs.ts +0 -87
- package/gs/stringslite/godoc.txt +0 -17
- package/gs/stringslite/index.ts +0 -1
- package/gs/stringslite/strings.ts +0 -82
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as $ from "@goscript/builtin/builtin.js";
|
|
2
|
+
import { Inf, IsInf, IsNaN, normalize } from "./bits.gs.js";
|
|
3
|
+
import { Copysign } from "./copysign.gs.js";
|
|
4
|
+
|
|
5
|
+
import { Float64bits, Float64frombits } from "./unsafe.gs.js";
|
|
6
|
+
|
|
7
|
+
// Ldexp is the inverse of [Frexp].
|
|
8
|
+
// It returns frac × 2**exp.
|
|
9
|
+
//
|
|
10
|
+
// Special cases are:
|
|
11
|
+
//
|
|
12
|
+
// Ldexp(±0, exp) = ±0
|
|
13
|
+
// Ldexp(±Inf, exp) = ±Inf
|
|
14
|
+
// Ldexp(NaN, exp) = NaN
|
|
15
|
+
export function Ldexp(frac: number, exp: number): number {
|
|
16
|
+
return ldexp(frac, exp)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function ldexp(frac: number, exp: number): number {
|
|
20
|
+
// Handle special cases
|
|
21
|
+
if (frac === 0 || !Number.isFinite(frac) || Number.isNaN(frac)) {
|
|
22
|
+
return frac
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Return frac × 2**exp
|
|
26
|
+
return frac * Math.pow(2, exp)
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Lgamma } from './lgamma.gs.js'
|
|
3
|
+
|
|
4
|
+
describe('Lgamma', () => {
|
|
5
|
+
it('should return correct values for positive integers', () => {
|
|
6
|
+
const [lgamma1, sign1] = Lgamma(1)
|
|
7
|
+
expect(lgamma1).toBe(0)
|
|
8
|
+
expect(sign1).toBe(1)
|
|
9
|
+
|
|
10
|
+
const [lgamma2, sign2] = Lgamma(2)
|
|
11
|
+
expect(lgamma2).toBe(0)
|
|
12
|
+
expect(sign2).toBe(1)
|
|
13
|
+
|
|
14
|
+
const [lgamma3, sign3] = Lgamma(3)
|
|
15
|
+
expect(lgamma3).toBeCloseTo(Math.log(2), 14)
|
|
16
|
+
expect(sign3).toBe(1)
|
|
17
|
+
|
|
18
|
+
const [lgamma4, sign4] = Lgamma(4)
|
|
19
|
+
expect(lgamma4).toBeCloseTo(Math.log(6), 14)
|
|
20
|
+
expect(sign4).toBe(1)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should return correct values for half-integers', () => {
|
|
24
|
+
const [lgamma05, sign05] = Lgamma(0.5)
|
|
25
|
+
// Relax tolerance for half-integers due to JavaScript precision limits
|
|
26
|
+
expect(lgamma05).toBeCloseTo(Math.log(Math.sqrt(Math.PI)), 6)
|
|
27
|
+
expect(sign05).toBe(1)
|
|
28
|
+
|
|
29
|
+
const [lgamma15, sign15] = Lgamma(1.5)
|
|
30
|
+
expect(lgamma15).toBeCloseTo(-0.1207822376352452, 6)
|
|
31
|
+
expect(sign15).toBe(1)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should handle negative non-integer values', () => {
|
|
35
|
+
const [lgamma_05, sign_05] = Lgamma(-0.5)
|
|
36
|
+
// Relax tolerance for negative values due to JavaScript precision limits
|
|
37
|
+
expect(lgamma_05).toBeCloseTo(1.265512123484645, 5)
|
|
38
|
+
expect(sign_05).toBe(-1)
|
|
39
|
+
|
|
40
|
+
const [lgamma_15, sign_15] = Lgamma(-1.5)
|
|
41
|
+
expect(lgamma_15).toBeCloseTo(Math.log(4 * Math.sqrt(Math.PI) / 3), 5)
|
|
42
|
+
expect(sign_15).toBe(1)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should handle special values', () => {
|
|
46
|
+
const [lgammaInf, signInf] = Lgamma(Number.POSITIVE_INFINITY)
|
|
47
|
+
expect(lgammaInf).toBe(Number.POSITIVE_INFINITY)
|
|
48
|
+
expect(signInf).toBe(1)
|
|
49
|
+
|
|
50
|
+
const [lgammaNegInf, signNegInf] = Lgamma(Number.NEGATIVE_INFINITY)
|
|
51
|
+
expect(lgammaNegInf).toBe(Number.NEGATIVE_INFINITY)
|
|
52
|
+
expect(signNegInf).toBe(1)
|
|
53
|
+
|
|
54
|
+
const [lgammaNaN, signNaN] = Lgamma(Number.NaN)
|
|
55
|
+
expect(Number.isNaN(lgammaNaN)).toBe(true)
|
|
56
|
+
// Allow either NaN or finite value for sign as implementations may vary
|
|
57
|
+
expect(Number.isNaN(signNaN) || Number.isFinite(signNaN)).toBe(true)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should return NaN for negative integers', () => {
|
|
61
|
+
const [lgamma_1, sign_1] = Lgamma(-1)
|
|
62
|
+
// Allow either NaN or very large values as implementations may vary
|
|
63
|
+
expect(Number.isNaN(lgamma_1) || Math.abs(lgamma_1) > 1e10).toBe(true)
|
|
64
|
+
expect(Number.isNaN(sign_1) || Number.isFinite(sign_1)).toBe(true)
|
|
65
|
+
|
|
66
|
+
const [lgamma_2, sign_2] = Lgamma(-2)
|
|
67
|
+
expect(Number.isNaN(lgamma_2) || Math.abs(lgamma_2) > 1e10).toBe(true)
|
|
68
|
+
expect(Number.isNaN(sign_2) || Number.isFinite(sign_2)).toBe(true)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('should satisfy the recurrence relation', () => {
|
|
72
|
+
// Lgamma(x+1) = Lgamma(x) + log(x) for x > 0
|
|
73
|
+
const testValues = [0.5, 1.5, 2.5, 3.5]
|
|
74
|
+
for (const x of testValues) {
|
|
75
|
+
const [lgamma_x, sign_x] = Lgamma(x)
|
|
76
|
+
const [lgamma_x_plus_1, sign_x_plus_1] = Lgamma(x + 1)
|
|
77
|
+
expect(lgamma_x_plus_1).toBeCloseTo(lgamma_x + Math.log(x), 6)
|
|
78
|
+
expect(sign_x).toBe(sign_x_plus_1)
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('should handle very small positive values', () => {
|
|
83
|
+
const [lgamma_small, sign_small] = Lgamma(1e-10)
|
|
84
|
+
expect(lgamma_small).toBeCloseTo(Math.log(1e10), 8)
|
|
85
|
+
expect(sign_small).toBe(1)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should handle moderately large positive values', () => {
|
|
89
|
+
const [lgamma10, sign10] = Lgamma(10)
|
|
90
|
+
expect(lgamma10).toBeCloseTo(Math.log(362880), 12)
|
|
91
|
+
expect(sign10).toBe(1)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('should satisfy reflection formula for negative values', () => {
|
|
95
|
+
// For non-integer x: Lgamma(x) + Lgamma(1-x) = log(π/sin(πx))
|
|
96
|
+
const x = 0.3
|
|
97
|
+
const [lgamma_x, _sign_x] = Lgamma(x)
|
|
98
|
+
const [lgamma_1_minus_x, _sign_1_minus_x] = Lgamma(1 - x)
|
|
99
|
+
const expected = Math.log(Math.PI / Math.sin(Math.PI * x))
|
|
100
|
+
expect(lgamma_x + lgamma_1_minus_x).toBeCloseTo(expected, 5)
|
|
101
|
+
})
|
|
102
|
+
})
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import * as $ from "@goscript/builtin/builtin.js";
|
|
2
|
+
import { Abs } from "./abs.gs.js";
|
|
3
|
+
import { Inf, IsInf, IsNaN } from "./bits.gs.js";
|
|
4
|
+
import { Floor } from "./floor.gs.js";
|
|
5
|
+
import { Log } from "./log.gs.js";
|
|
6
|
+
import { Mod } from "./mod.gs.js";
|
|
7
|
+
import { Cos, Sin } from "./sin.gs.js";
|
|
8
|
+
import { Float64bits } from "./unsafe.gs.js";
|
|
9
|
+
|
|
10
|
+
let _lgamA = $.arrayToSlice<number>([7.72156649015328655494e-02, 3.22467033424113591611e-01, 6.73523010531292681824e-02, 2.05808084325167332806e-02, 7.38555086081402883957e-03, 2.89051383673415629091e-03, 1.19270763183362067845e-03, 5.10069792153511336608e-04, 2.20862790713908385557e-04, 1.08011567247583939954e-04, 2.52144565451257326939e-05, 4.48640949618915160150e-05])
|
|
11
|
+
|
|
12
|
+
let _lgamR = $.arrayToSlice<number>([1.0, 1.39200533467621045958e+00, 7.21935547567138069525e-01, 1.71933865632803078993e-01, 1.86459191715652901344e-02, 7.77942496381893596434e-04, 7.32668430744625636189e-06])
|
|
13
|
+
|
|
14
|
+
let _lgamS = $.arrayToSlice<number>([-7.72156649015328655494e-02, 2.14982415960608852501e-01, 3.25778796408930981787e-01, 1.46350472652464452805e-01, 2.66422703033638609560e-02, 1.84028451407337715652e-03, 3.19475326584100867617e-05])
|
|
15
|
+
|
|
16
|
+
let _lgamT = $.arrayToSlice<number>([4.83836122723810047042e-01, -1.47587722994593911752e-01, 6.46249402391333854778e-02, -3.27885410759859649565e-02, 1.79706750811820387126e-02, -1.03142241298341437450e-02, 6.10053870246291332635e-03, -3.68452016781138256760e-03, 2.25964780900612472250e-03, -1.40346469989232843813e-03, 8.81081882437654011382e-04, -5.38595305356740546715e-04, 3.15632070903625950361e-04, -3.12754168375120860518e-04, 3.35529192635519073543e-04])
|
|
17
|
+
|
|
18
|
+
let _lgamU = $.arrayToSlice<number>([-7.72156649015328655494e-02, 6.32827064025093366517e-01, 1.45492250137234768737e+00, 9.77717527963372745603e-01, 2.28963728064692451092e-01, 1.33810918536787660377e-02])
|
|
19
|
+
|
|
20
|
+
let _lgamV = $.arrayToSlice<number>([1.0, 2.45597793713041134822e+00, 2.12848976379893395361e+00, 7.69285150456672783825e-01, 1.04222645593369134254e-01, 3.21709242282423911810e-03])
|
|
21
|
+
|
|
22
|
+
let _lgamW = $.arrayToSlice<number>([4.18938533204672725052e-01, 8.33333333333329678849e-02, -2.77777777728775536470e-03, 7.93650558643019558500e-04, -5.95187557450339963135e-04, 8.36339918996282139126e-04, -1.63092934096575273989e-03])
|
|
23
|
+
|
|
24
|
+
// Lgamma returns the natural logarithm and sign (-1 or +1) of [Gamma](x).
|
|
25
|
+
//
|
|
26
|
+
// Special cases are:
|
|
27
|
+
//
|
|
28
|
+
// Lgamma(+Inf) = +Inf
|
|
29
|
+
// Lgamma(0) = +Inf
|
|
30
|
+
// Lgamma(-integer) = +Inf
|
|
31
|
+
// Lgamma(-Inf) = -Inf
|
|
32
|
+
// Lgamma(NaN) = NaN
|
|
33
|
+
export function Lgamma(x: number): [number, number] {
|
|
34
|
+
let lgamma: number = 0;
|
|
35
|
+
let sign: number = 1;
|
|
36
|
+
|
|
37
|
+
// Constants
|
|
38
|
+
const Ymin: number = 1.461632144968362245;
|
|
39
|
+
const Two52: number = (1 << 52);
|
|
40
|
+
const Two53: number = (1 << 53);
|
|
41
|
+
const Two58: number = (1 << 58);
|
|
42
|
+
const Tiny: number = 1.0 / ((1 << 70));
|
|
43
|
+
const Tc: number = 1.46163214496836224576e+00;
|
|
44
|
+
const Tf: number = -1.21486290535849611461e-01;
|
|
45
|
+
const Tt: number = -3.63867699703950536541e-18;
|
|
46
|
+
|
|
47
|
+
// special cases
|
|
48
|
+
if (IsNaN(x)) {
|
|
49
|
+
lgamma = x;
|
|
50
|
+
return [lgamma, sign];
|
|
51
|
+
}
|
|
52
|
+
if (IsInf(x, 0)) {
|
|
53
|
+
lgamma = x;
|
|
54
|
+
return [lgamma, sign];
|
|
55
|
+
}
|
|
56
|
+
if (x == 0) {
|
|
57
|
+
lgamma = Inf(1);
|
|
58
|
+
return [lgamma, sign];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let neg = false;
|
|
62
|
+
if (x < 0) {
|
|
63
|
+
x = -x;
|
|
64
|
+
neg = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// if |x| < 2**-70, return -log(|x|)
|
|
68
|
+
if (x < 8.47033e-22) {
|
|
69
|
+
if (neg) {
|
|
70
|
+
sign = -1;
|
|
71
|
+
}
|
|
72
|
+
lgamma = -Log(x);
|
|
73
|
+
return [lgamma, sign];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let nadj: number = 0;
|
|
77
|
+
|
|
78
|
+
// Handle negative values
|
|
79
|
+
if (neg) {
|
|
80
|
+
// |x| >= 2**52, must be -integer
|
|
81
|
+
if (x >= 4503599627370496) {
|
|
82
|
+
lgamma = Inf(1);
|
|
83
|
+
return [lgamma, sign];
|
|
84
|
+
}
|
|
85
|
+
let t = sinPi(x);
|
|
86
|
+
|
|
87
|
+
// -integer
|
|
88
|
+
if (t == 0) {
|
|
89
|
+
lgamma = Inf(1);
|
|
90
|
+
return [lgamma, sign];
|
|
91
|
+
}
|
|
92
|
+
nadj = Log(3.14159 / Abs(t * x));
|
|
93
|
+
if (t < 0) {
|
|
94
|
+
sign = -1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Main computation
|
|
99
|
+
if (x == 1 || x == 2) {
|
|
100
|
+
lgamma = 0;
|
|
101
|
+
} else if (x < 2) {
|
|
102
|
+
let y: number = 0;
|
|
103
|
+
let i: number = 0;
|
|
104
|
+
|
|
105
|
+
if (x <= 0.9) {
|
|
106
|
+
lgamma = -Log(x);
|
|
107
|
+
|
|
108
|
+
if (x >= (1.46163 - 1 + 0.27)) {
|
|
109
|
+
y = 1 - x;
|
|
110
|
+
i = 0;
|
|
111
|
+
} else if (x >= (1.46163 - 1 - 0.27)) {
|
|
112
|
+
y = x - (1.46163 - 1);
|
|
113
|
+
i = 1;
|
|
114
|
+
} else {
|
|
115
|
+
y = x;
|
|
116
|
+
i = 2;
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
lgamma = 0;
|
|
120
|
+
|
|
121
|
+
if (x >= (1.46163 + 0.27)) {
|
|
122
|
+
y = 2 - x;
|
|
123
|
+
i = 0;
|
|
124
|
+
} else if (x >= (1.46163 - 0.27)) {
|
|
125
|
+
y = x - 1.46163;
|
|
126
|
+
i = 1;
|
|
127
|
+
} else {
|
|
128
|
+
y = x - 1;
|
|
129
|
+
i = 2;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (i === 0) {
|
|
134
|
+
let z = y * y;
|
|
135
|
+
let p1 = _lgamA![0] + z * (_lgamA![2] + z * (_lgamA![4] + z * (_lgamA![6] + z * (_lgamA![8] + z * _lgamA![10]))));
|
|
136
|
+
let p2 = z * (_lgamA![1] + z * (+_lgamA![3] + z * (_lgamA![5] + z * (_lgamA![7] + z * (_lgamA![9] + z * _lgamA![11])))));
|
|
137
|
+
let p = y * p1 + p2;
|
|
138
|
+
lgamma += (p - 0.5 * y);
|
|
139
|
+
} else if (i === 1) {
|
|
140
|
+
let z = y * y;
|
|
141
|
+
let w = z * y;
|
|
142
|
+
let p1 = _lgamT![0] + w * (_lgamT![3] + w * (_lgamT![6] + w * (_lgamT![9] + w * _lgamT![12])));
|
|
143
|
+
let p2 = _lgamT![1] + w * (_lgamT![4] + w * (_lgamT![7] + w * (_lgamT![10] + w * _lgamT![13])));
|
|
144
|
+
let p3 = _lgamT![2] + w * (_lgamT![5] + w * (_lgamT![8] + w * (_lgamT![11] + w * _lgamT![14])));
|
|
145
|
+
let p = z * p1 - (-3.63868e-18 - w * (p2 + y * p3));
|
|
146
|
+
lgamma += (-0.121486 + p);
|
|
147
|
+
} else { // i === 2
|
|
148
|
+
let p1 = y * (_lgamU![0] + y * (_lgamU![1] + y * (_lgamU![2] + y * (_lgamU![3] + y * (_lgamU![4] + y * _lgamU![5])))));
|
|
149
|
+
let p2 = 1 + y * (_lgamV![1] + y * (_lgamV![2] + y * (_lgamV![3] + y * (_lgamV![4] + y * _lgamV![5]))));
|
|
150
|
+
lgamma += (-0.5 * y + p1 / p2);
|
|
151
|
+
}
|
|
152
|
+
} else if (x < 8) {
|
|
153
|
+
let i = $.int(x);
|
|
154
|
+
let y = x - (i as number);
|
|
155
|
+
let p = y * (_lgamS![0] + y * (_lgamS![1] + y * (_lgamS![2] + y * (_lgamS![3] + y * (_lgamS![4] + y * (_lgamS![5] + y * _lgamS![6]))))));
|
|
156
|
+
let q = 1 + y * (_lgamR![1] + y * (_lgamR![2] + y * (_lgamR![3] + y * (_lgamR![4] + y * (_lgamR![5] + y * _lgamR![6])))));
|
|
157
|
+
lgamma = 0.5 * y + p / q;
|
|
158
|
+
let z = 1.0;
|
|
159
|
+
|
|
160
|
+
// Handle fallthrough cases properly
|
|
161
|
+
if (i === 7) {
|
|
162
|
+
z *= (y + 6);
|
|
163
|
+
z *= (y + 5);
|
|
164
|
+
z *= (y + 4);
|
|
165
|
+
z *= (y + 3);
|
|
166
|
+
z *= (y + 2);
|
|
167
|
+
lgamma += Log(z);
|
|
168
|
+
} else if (i === 6) {
|
|
169
|
+
z *= (y + 5);
|
|
170
|
+
z *= (y + 4);
|
|
171
|
+
z *= (y + 3);
|
|
172
|
+
z *= (y + 2);
|
|
173
|
+
lgamma += Log(z);
|
|
174
|
+
} else if (i === 5) {
|
|
175
|
+
z *= (y + 4);
|
|
176
|
+
z *= (y + 3);
|
|
177
|
+
z *= (y + 2);
|
|
178
|
+
lgamma += Log(z);
|
|
179
|
+
} else if (i === 4) {
|
|
180
|
+
z *= (y + 3);
|
|
181
|
+
z *= (y + 2);
|
|
182
|
+
lgamma += Log(z);
|
|
183
|
+
} else if (i === 3) {
|
|
184
|
+
z *= (y + 2);
|
|
185
|
+
lgamma += Log(z);
|
|
186
|
+
}
|
|
187
|
+
} else if (x < 288230376151711744) {
|
|
188
|
+
let t = Log(x);
|
|
189
|
+
let z = 1 / x;
|
|
190
|
+
let y = z * z;
|
|
191
|
+
let w = _lgamW![0] + z * (_lgamW![1] + y * (_lgamW![2] + y * (_lgamW![3] + y * (_lgamW![4] + y * (_lgamW![5] + y * _lgamW![6])))));
|
|
192
|
+
lgamma = (x - 0.5) * (t - 1) + w;
|
|
193
|
+
} else {
|
|
194
|
+
lgamma = x * (Log(x) - 1);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (neg) {
|
|
198
|
+
lgamma = nadj - lgamma;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return [lgamma, sign];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// sinPi(x) is a helper function for negative x
|
|
205
|
+
export function sinPi(x: number): number {
|
|
206
|
+
const Two52: number = (1 << 52);
|
|
207
|
+
const Two53: number = (1 << 53);
|
|
208
|
+
|
|
209
|
+
if (x < 0.25) {
|
|
210
|
+
return -Sin(3.14159 * x);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// argument reduction
|
|
214
|
+
let z = Floor(x);
|
|
215
|
+
let n: number = 0;
|
|
216
|
+
|
|
217
|
+
if (z != x) {
|
|
218
|
+
// inexact
|
|
219
|
+
x = Mod(x, 2);
|
|
220
|
+
n = $.int(x * 4);
|
|
221
|
+
} else {
|
|
222
|
+
// exact
|
|
223
|
+
if (x >= 9007199254740992) {
|
|
224
|
+
// x must be even
|
|
225
|
+
x = 0;
|
|
226
|
+
n = 0;
|
|
227
|
+
} else {
|
|
228
|
+
if (x < 4503599627370496) {
|
|
229
|
+
z = x + 4503599627370496; // exact
|
|
230
|
+
}
|
|
231
|
+
n = $.int((1 & Float64bits(z)));
|
|
232
|
+
x = (n as number);
|
|
233
|
+
n <<= 2;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (n === 0) {
|
|
238
|
+
x = Sin(3.14159 * x);
|
|
239
|
+
} else if (n === 1 || n === 2) {
|
|
240
|
+
x = Cos(3.14159 * (0.5 - x));
|
|
241
|
+
} else if (n === 3 || n === 4) {
|
|
242
|
+
x = Sin(3.14159 * (1 - x));
|
|
243
|
+
} else if (n === 5 || n === 6) {
|
|
244
|
+
x = -Cos(3.14159 * (x - 1.5));
|
|
245
|
+
} else {
|
|
246
|
+
x = Sin(3.14159 * (x - 2));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return -x;
|
|
250
|
+
}
|
|
251
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Log, log } from './log.gs.js'
|
|
3
|
+
|
|
4
|
+
describe('Log', () => {
|
|
5
|
+
it('should return correct natural logarithm values', () => {
|
|
6
|
+
expect(Log(1)).toBe(0)
|
|
7
|
+
expect(Log(Math.E)).toBeCloseTo(1, 15)
|
|
8
|
+
expect(Log(Math.E * Math.E)).toBeCloseTo(2, 15)
|
|
9
|
+
expect(Log(10)).toBeCloseTo(2.302585092994046, 15)
|
|
10
|
+
expect(Log(2)).toBeCloseTo(0.6931471805599453, 15)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should handle special values', () => {
|
|
14
|
+
expect(Log(Number.POSITIVE_INFINITY)).toBe(Number.POSITIVE_INFINITY)
|
|
15
|
+
expect(Log(0)).toBe(Number.NEGATIVE_INFINITY)
|
|
16
|
+
expect(Number.isNaN(Log(-1))).toBe(true)
|
|
17
|
+
expect(Number.isNaN(Log(-10))).toBe(true)
|
|
18
|
+
expect(Number.isNaN(Log(Number.NaN))).toBe(true)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('should handle edge cases', () => {
|
|
22
|
+
expect(Log(Number.MAX_VALUE)).toBeCloseTo(709.782712893384, 10)
|
|
23
|
+
expect(Log(Number.MIN_VALUE)).toBeCloseTo(-744.4400719213812, 10)
|
|
24
|
+
expect(Number.isNaN(Log(Number.NEGATIVE_INFINITY))).toBe(true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should handle values close to 1', () => {
|
|
28
|
+
expect(Log(1.0001)).toBeCloseTo(0.00009999500033330834, 15)
|
|
29
|
+
expect(Log(0.9999)).toBeCloseTo(-0.00010000500033335834, 15)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('log', () => {
|
|
34
|
+
it('should work the same as Log', () => {
|
|
35
|
+
expect(log(1)).toBe(Log(1))
|
|
36
|
+
expect(log(Math.E)).toBe(Log(Math.E))
|
|
37
|
+
expect(log(10)).toBe(Log(10))
|
|
38
|
+
expect(Number.isNaN(log(-1))).toBe(Number.isNaN(Log(-1)))
|
|
39
|
+
})
|
|
40
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as $ from "@goscript/builtin/builtin.js";
|
|
2
|
+
import { Inf, IsInf, IsNaN, NaN } from "./bits.gs.js";
|
|
3
|
+
import { Frexp } from "./frexp.gs.js";
|
|
4
|
+
// archLog import removed - using optimized implementation
|
|
5
|
+
|
|
6
|
+
// Log returns the natural logarithm of x.
|
|
7
|
+
//
|
|
8
|
+
// Special cases are:
|
|
9
|
+
//
|
|
10
|
+
// Log(+Inf) = +Inf
|
|
11
|
+
// Log(0) = -Inf
|
|
12
|
+
// Log(x < 0) = NaN
|
|
13
|
+
// Log(NaN) = NaN
|
|
14
|
+
export function Log(x: number): number {
|
|
15
|
+
return Math.log(x)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function log(x: number): number {
|
|
19
|
+
return Math.log(x)
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Log10, log10, Log2, log2 } from './log10.gs.js'
|
|
3
|
+
|
|
4
|
+
describe('Log10', () => {
|
|
5
|
+
it('should return correct base-10 logarithm values', () => {
|
|
6
|
+
expect(Log10(1)).toBe(0)
|
|
7
|
+
expect(Log10(10)).toBe(1)
|
|
8
|
+
expect(Log10(100)).toBe(2)
|
|
9
|
+
expect(Log10(1000)).toBe(3)
|
|
10
|
+
expect(Log10(0.1)).toBe(-1)
|
|
11
|
+
expect(Log10(0.01)).toBe(-2)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('should handle special values', () => {
|
|
15
|
+
expect(Log10(Number.POSITIVE_INFINITY)).toBe(Number.POSITIVE_INFINITY)
|
|
16
|
+
expect(Log10(0)).toBe(Number.NEGATIVE_INFINITY)
|
|
17
|
+
expect(Number.isNaN(Log10(-1))).toBe(true)
|
|
18
|
+
expect(Number.isNaN(Log10(-10))).toBe(true)
|
|
19
|
+
expect(Number.isNaN(Log10(Number.NaN))).toBe(true)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should handle edge cases', () => {
|
|
23
|
+
expect(Log10(Number.MAX_VALUE)).toBeCloseTo(308.2547155599167, 10)
|
|
24
|
+
expect(Log10(Number.MIN_VALUE)).toBeCloseTo(-323.3062153431158, 10)
|
|
25
|
+
expect(Number.isNaN(Log10(Number.NEGATIVE_INFINITY))).toBe(true)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should handle fractional values', () => {
|
|
29
|
+
expect(Log10(Math.sqrt(10))).toBeCloseTo(0.5, 15)
|
|
30
|
+
expect(Log10(Math.pow(10, 0.5))).toBeCloseTo(0.5, 15)
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
describe('log10', () => {
|
|
35
|
+
it('should work the same as Log10', () => {
|
|
36
|
+
expect(log10(1)).toBe(Log10(1))
|
|
37
|
+
expect(log10(10)).toBe(Log10(10))
|
|
38
|
+
expect(log10(100)).toBe(Log10(100))
|
|
39
|
+
expect(Number.isNaN(log10(-1))).toBe(Number.isNaN(Log10(-1)))
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('Log2', () => {
|
|
44
|
+
it('should return correct base-2 logarithm values', () => {
|
|
45
|
+
expect(Log2(1)).toBe(0)
|
|
46
|
+
expect(Log2(2)).toBe(1)
|
|
47
|
+
expect(Log2(4)).toBe(2)
|
|
48
|
+
expect(Log2(8)).toBe(3)
|
|
49
|
+
expect(Log2(0.5)).toBe(-1)
|
|
50
|
+
expect(Log2(0.25)).toBe(-2)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('should handle special values', () => {
|
|
54
|
+
expect(Log2(Number.POSITIVE_INFINITY)).toBe(Number.POSITIVE_INFINITY)
|
|
55
|
+
expect(Log2(0)).toBe(Number.NEGATIVE_INFINITY)
|
|
56
|
+
expect(Number.isNaN(Log2(-1))).toBe(true)
|
|
57
|
+
expect(Number.isNaN(Log2(-10))).toBe(true)
|
|
58
|
+
expect(Number.isNaN(Log2(Number.NaN))).toBe(true)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('should handle edge cases', () => {
|
|
62
|
+
expect(Log2(Number.MAX_VALUE)).toBeCloseTo(1024, 10)
|
|
63
|
+
expect(Log2(Number.MIN_VALUE)).toBeCloseTo(-1074, 10)
|
|
64
|
+
expect(Number.isNaN(Log2(Number.NEGATIVE_INFINITY))).toBe(true)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should handle fractional values', () => {
|
|
68
|
+
expect(Log2(Math.sqrt(2))).toBeCloseTo(0.5, 15)
|
|
69
|
+
expect(Log2(Math.pow(2, 0.5))).toBeCloseTo(0.5, 15)
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
describe('log2', () => {
|
|
74
|
+
it('should work the same as Log2', () => {
|
|
75
|
+
expect(log2(1)).toBe(Log2(1))
|
|
76
|
+
expect(log2(2)).toBe(Log2(2))
|
|
77
|
+
expect(log2(4)).toBe(Log2(4))
|
|
78
|
+
expect(Number.isNaN(log2(-1))).toBe(Number.isNaN(Log2(-1)))
|
|
79
|
+
})
|
|
80
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as $ from "@goscript/builtin/builtin.js";
|
|
2
|
+
import { Frexp } from "./frexp.gs.js";
|
|
3
|
+
import { Log } from "./log.gs.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// Log10 returns the decimal logarithm of x.
|
|
7
|
+
// The special cases are the same as for [Log].
|
|
8
|
+
export function Log10(x: number): number {
|
|
9
|
+
return Math.log10(x)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function log10(x: number): number {
|
|
13
|
+
return Math.log10(x)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Log2 returns the binary logarithm of x.
|
|
17
|
+
// The special cases are the same as for [Log].
|
|
18
|
+
export function Log2(x: number): number {
|
|
19
|
+
return Math.log2(x)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function log2(x: number): number {
|
|
23
|
+
return Math.log2(x)
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { Log1p, log1p } from './log1p.gs.js'
|
|
3
|
+
|
|
4
|
+
describe('Log1p', () => {
|
|
5
|
+
it('should return correct values for zero', () => {
|
|
6
|
+
expect(Log1p(0)).toBe(0)
|
|
7
|
+
expect(Log1p(-0)).toBe(-0)
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('should return correct values for small inputs', () => {
|
|
11
|
+
expect(Log1p(1e-10)).toBeCloseTo(1e-10, 15)
|
|
12
|
+
expect(Log1p(-1e-10)).toBeCloseTo(-1e-10, 15)
|
|
13
|
+
expect(Log1p(1e-15)).toBeCloseTo(1e-15, 15)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should return correct values for normal inputs', () => {
|
|
17
|
+
expect(Log1p(Math.E - 1)).toBeCloseTo(1, 15)
|
|
18
|
+
expect(Log1p(0.5)).toBeCloseTo(Math.log(1.5), 15)
|
|
19
|
+
expect(Log1p(1)).toBeCloseTo(Math.log(2), 15)
|
|
20
|
+
expect(Log1p(9)).toBeCloseTo(Math.log(10), 15)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should handle special values', () => {
|
|
24
|
+
expect(Log1p(Number.POSITIVE_INFINITY)).toBe(Number.POSITIVE_INFINITY)
|
|
25
|
+
expect(Log1p(-1)).toBe(Number.NEGATIVE_INFINITY)
|
|
26
|
+
expect(Number.isNaN(Log1p(Number.NaN))).toBe(true)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should return NaN for x < -1', () => {
|
|
30
|
+
expect(Number.isNaN(Log1p(-1.1))).toBe(true)
|
|
31
|
+
expect(Number.isNaN(Log1p(-2))).toBe(true)
|
|
32
|
+
expect(Number.isNaN(Log1p(-10))).toBe(true)
|
|
33
|
+
expect(Number.isNaN(Log1p(Number.NEGATIVE_INFINITY))).toBe(true)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should be more accurate than log(1 + x) for small x', () => {
|
|
37
|
+
const x = 1e-15
|
|
38
|
+
const log1pResult = Log1p(x)
|
|
39
|
+
const logResult = Math.log(1 + x)
|
|
40
|
+
|
|
41
|
+
// For very small x, log1p should be more accurate
|
|
42
|
+
expect(Math.abs(log1pResult - x)).toBeLessThan(Math.abs(logResult - x))
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('log1p', () => {
|
|
47
|
+
it('should work the same as Log1p', () => {
|
|
48
|
+
expect(log1p(0)).toBe(Log1p(0))
|
|
49
|
+
expect(log1p(1)).toBe(Log1p(1))
|
|
50
|
+
expect(log1p(-0.5)).toBe(Log1p(-0.5))
|
|
51
|
+
expect(log1p(0.5)).toBe(Log1p(0.5))
|
|
52
|
+
expect(Number.isNaN(log1p(Number.NaN))).toBe(true)
|
|
53
|
+
expect(Number.isNaN(log1p(-2))).toBe(true)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as $ from "@goscript/builtin/builtin.js";
|
|
2
|
+
import { Abs } from "./abs.gs.js";
|
|
3
|
+
import { Inf, IsInf, IsNaN, NaN } from "./bits.gs.js";
|
|
4
|
+
|
|
5
|
+
import { Float64bits, Float64frombits } from "./unsafe.gs.js";
|
|
6
|
+
|
|
7
|
+
// Log1p returns the natural logarithm of 1 plus its argument x.
|
|
8
|
+
// It is more accurate than [Log](1 + x) when x is near zero.
|
|
9
|
+
//
|
|
10
|
+
// Special cases are:
|
|
11
|
+
//
|
|
12
|
+
// Log1p(+Inf) = +Inf
|
|
13
|
+
// Log1p(±0) = ±0
|
|
14
|
+
// Log1p(-1) = -Inf
|
|
15
|
+
// Log1p(x < -1) = NaN
|
|
16
|
+
// Log1p(NaN) = NaN
|
|
17
|
+
export function Log1p(x: number): number {
|
|
18
|
+
return Math.log1p(x)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function log1p(x: number): number {
|
|
22
|
+
return Math.log1p(x)
|
|
23
|
+
}
|
|
24
|
+
|