builtin: real/imag/complex; c/math/cmplx; patch: math/cmplx

This commit is contained in:
xushiwei
2024-06-20 10:00:47 +08:00
parent 1566a834e1
commit de6535b722
9 changed files with 274 additions and 24 deletions

View File

@@ -206,8 +206,9 @@ Here are the Go packages that can be imported correctly:
* [unicode](https://pkg.go.dev/unicode) * [unicode](https://pkg.go.dev/unicode)
* [unicode/utf8](https://pkg.go.dev/unicode/utf8) * [unicode/utf8](https://pkg.go.dev/unicode/utf8)
* [unicode/utf16](https://pkg.go.dev/unicode/utf16) * [unicode/utf16](https://pkg.go.dev/unicode/utf16)
* [math/bits](https://pkg.go.dev/math/bits)
* [math](https://pkg.go.dev/math) * [math](https://pkg.go.dev/math)
* [math/bits](https://pkg.go.dev/math/bits)
* [math/cmplx](https://pkg.go.dev/math/cmplx)
* [syscall](https://pkg.go.dev/syscall) (partially) * [syscall](https://pkg.go.dev/syscall) (partially)
* [sync](https://pkg.go.dev/sync) (partially) * [sync](https://pkg.go.dev/sync) (partially)
* [sync/atomic](https://pkg.go.dev/sync/atomic) (partially) * [sync/atomic](https://pkg.go.dev/sync/atomic) (partially)
@@ -217,8 +218,8 @@ Here are the Go packages that can be imported correctly:
- [Go 1.20+](https://go.dev) (build only) - [Go 1.20+](https://go.dev) (build only)
- [LLVM 17](https://llvm.org) - [LLVM 17](https://llvm.org)
- [Clang 17](https://clang.llvm.org)
- [LLD 17](https://lld.llvm.org) - [LLD 17](https://lld.llvm.org)
- [Clang 17](https://clang.llvm.org)
- [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/) - [pkg-config 0.29+](https://www.freedesktop.org/wiki/Software/pkg-config/)
- [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/) - [bdwgc/libgc 8.0+](https://www.hboehm.info/gc/)
- [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [`github.com/goplus/llgo/c/cjson`](https://pkg.go.dev/github.com/goplus/llgo/c/cjson)) - [cJSON 1.7+](https://github.com/DaveGamble/cJSON) (optional, for [`github.com/goplus/llgo/c/cjson`](https://pkg.go.dev/github.com/goplus/llgo/c/cjson))

9
_demo/complex/cmplx.go Normal file
View File

@@ -0,0 +1,9 @@
package main
import (
"math/cmplx"
)
func main() {
println("abs(3+4i):", cmplx.Abs(3+4i))
}

89
c/math/cmplx/complex.go Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cmplx
import (
_ "unsafe"
)
const (
LLGoPackage = "decl"
)
// -----------------------------------------------------------------------------
//go:linkname Abs C.cabs
func Abs(z complex128) float64
//go:linkname Acos C.cacos
func Acos(z complex128) complex128
//go:linkname Acosh C.cacosh
func Acosh(z complex128) complex128
//go:linkname Asin C.casin
func Asin(z complex128) complex128
//go:linkname Asinh C.casinh
func Asinh(z complex128) complex128
//go:linkname Atan C.catan
func Atan(z complex128) complex128
//go:linkname Atanh C.catanh
func Atanh(z complex128) complex128
//go:linkname Cos C.ccos
func Cos(z complex128) complex128
//go:linkname Cosh C.ccosh
func Cosh(z complex128) complex128
//go:linkname Exp C.cexp
func Exp(z complex128) complex128
//go:linkname Log C.clog
func Log(z complex128) complex128
//go:linkname Log10 C.clog10
func Log10(z complex128) complex128
//go:linkname Arg C.carg
func Arg(z complex128) float64
//go:linkname Phase C.carg
func Phase(z complex128) float64
//go:linkname Pow C.cpow
func Pow(x, y complex128) complex128
//go:linkname Sin C.csin
func Sin(z complex128) complex128
//go:linkname Sinh C.csinh
func Sinh(z complex128) complex128
//go:linkname Sqrt C.csqrt
func Sqrt(z complex128) complex128
//go:linkname Tan C.ctan
func Tan(z complex128) complex128
//go:linkname Tanh C.ctanh
func Tanh(z complex128) complex128
// -----------------------------------------------------------------------------

View File

@@ -722,6 +722,7 @@ var hasAltPkg = map[string]none{
"io": {}, "io": {},
"io/fs": {}, "io/fs": {},
"math": {}, "math": {},
"math/cmplx": {},
"sync": {}, "sync": {},
"sync/atomic": {}, "sync/atomic": {},
"syscall": {}, "syscall": {},

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cmplx
import (
_ "unsafe"
)
const (
LLGoPackage = true
)
// -----------------------------------------------------------------------------
//go:linkname Abs C.cabs
func Abs(z complex128) float64
//go:linkname Acos C.cacos
func Acos(z complex128) complex128
//go:linkname Acosh C.cacosh
func Acosh(z complex128) complex128
//go:linkname Asin C.casin
func Asin(z complex128) complex128
//go:linkname Asinh C.casinh
func Asinh(z complex128) complex128
//go:linkname Atan C.catan
func Atan(z complex128) complex128
//go:linkname Atanh C.catanh
func Atanh(z complex128) complex128
//go:linkname Cos C.ccos
func Cos(z complex128) complex128
//go:linkname Cosh C.ccosh
func Cosh(z complex128) complex128
//go:linkname Exp C.cexp
func Exp(z complex128) complex128
//go:linkname Log C.clog
func Log(z complex128) complex128
//go:linkname Log10 C.clog10
func Log10(z complex128) complex128
//go:linkname Phase C.carg
func Phase(z complex128) float64
//go:linkname Pow C.cpow
func Pow(x, y complex128) complex128
//go:linkname Sin C.csin
func Sin(z complex128) complex128
//go:linkname Sinh C.csinh
func Sinh(z complex128) complex128
//go:linkname Sqrt C.csqrt
func Sqrt(z complex128) complex128
//go:linkname Tan C.ctan
func Tan(z complex128) complex128
//go:linkname Tanh C.ctanh
func Tanh(z complex128) complex128
// -----------------------------------------------------------------------------

View File

@@ -66,6 +66,21 @@ func (b Builder) getField(x Expr, idx int) Expr {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
func (b Builder) Complex(r, i Expr) Expr {
if debugInstr {
log.Printf("Complex %v, %v\n", r.impl, i.impl)
}
prog := b.Prog
var t Type
switch kind := r.raw.Type.Underlying().(*types.Basic).Kind(); kind {
case types.Float64:
t = prog.Complex128()
case types.Float32:
t = prog.Complex64()
}
return b.aggregateValue(t, r.impl, i.impl)
}
// MakeString creates a new string from a C string pointer and length. // MakeString creates a new string from a C string pointer and length.
func (b Builder) MakeString(cstr Expr, n ...Expr) (ret Expr) { func (b Builder) MakeString(cstr Expr, n ...Expr) (ret Expr) {
if debugInstr { if debugInstr {

View File

@@ -168,11 +168,20 @@ func (p Program) IntVal(v uint64, t Type) Expr {
return Expr{ret, t} return Expr{ret, t}
} }
// FloatVal returns a float constant expression.
func (p Program) FloatVal(v float64, t Type) Expr { func (p Program) FloatVal(v float64, t Type) Expr {
ret := llvm.ConstFloat(t.ll, v) ret := llvm.ConstFloat(t.ll, v)
return Expr{ret, t} return Expr{ret, t}
} }
// ComplexVal returns a complex constant expression.
func (p Program) ComplexVal(v complex128, t Type) Expr {
flt := p.Field(t, 0)
re := p.FloatVal(real(v), flt)
im := p.FloatVal(imag(v), flt)
return Expr{llvm.ConstStruct([]llvm.Value{re.impl, im.impl}, false), t}
}
// Val returns a constant expression. // Val returns a constant expression.
func (p Program) Val(v interface{}) Expr { func (p Program) Val(v interface{}) Expr {
switch v := v.(type) { switch v := v.(type) {
@@ -211,11 +220,16 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
if v, exact := constant.Uint64Val(v); exact { if v, exact := constant.Uint64Val(v); exact {
return prog.IntVal(v, typ) return prog.IntVal(v, typ)
} }
case kind == types.Float32 || kind == types.Float64: case kind == types.Float64 || kind == types.Float32:
v, _ := constant.Float64Val(v) v, _ := constant.Float64Val(v)
return prog.FloatVal(v, typ) return prog.FloatVal(v, typ)
case kind == types.String: case kind == types.String:
return Expr{b.Str(constant.StringVal(v)).impl, typ} return Expr{b.Str(constant.StringVal(v)).impl, typ}
case kind == types.Complex128 || kind == types.Complex64:
v = constant.ToComplex(v)
re, _ := constant.Float64Val(constant.Real(v))
im, _ := constant.Float64Val(constant.Imag(v))
return prog.ComplexVal(complex(re, im), typ)
} }
} }
panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw)) panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw))
@@ -941,6 +955,12 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
return b.Recover() return b.Recover()
case "print", "println": case "print", "println":
return b.PrintEx(fn == "println", args...) return b.PrintEx(fn == "println", args...)
case "complex":
return b.Complex(args[0], args[1])
case "real":
return b.getField(args[0], 0)
case "imag":
return b.getField(args[0], 1)
case "String": // unsafe.String case "String": // unsafe.String
return b.unsafeString(args[0].impl, args[1].impl) return b.unsafeString(args[0].impl, args[1].impl)
case "Slice": // unsafe.Slice case "Slice": // unsafe.Slice

View File

@@ -125,15 +125,16 @@ type aProgram struct {
voidType llvm.Type voidType llvm.Type
voidPtrTy llvm.Type voidPtrTy llvm.Type
c64Type llvm.Type
c128Type llvm.Type
rtStringTy llvm.Type rtStringTy llvm.Type
rtEfaceTy llvm.Type rtEfaceTy llvm.Type
rtIfaceTy llvm.Type rtIfaceTy llvm.Type
rtSliceTy llvm.Type rtSliceTy llvm.Type
rtMapTy llvm.Type rtMapTy llvm.Type
anyTy Type anyTy Type
//anyPtr Type
//anyPPtr Type
voidTy Type voidTy Type
voidPtr Type voidPtr Type
voidPPtr Type voidPPtr Type
@@ -147,6 +148,8 @@ type aProgram struct {
uintTy Type uintTy Type
f64Ty Type f64Ty Type
f32Ty Type f32Ty Type
c128Ty Type
c64Ty Type
byteTy Type byteTy Type
i32Ty Type i32Ty Type
u32Ty Type u32Ty Type
@@ -284,6 +287,24 @@ func (p Program) rtString() llvm.Type {
return p.rtStringTy return p.rtStringTy
} }
func (p Program) tyComplex64() llvm.Type {
if p.c64Type.IsNil() {
ctx := p.ctx
f32 := ctx.FloatType()
p.c64Type = ctx.StructType([]llvm.Type{f32, f32}, false)
}
return p.c64Type
}
func (p Program) tyComplex128() llvm.Type {
if p.c128Type.IsNil() {
ctx := p.ctx
f64 := ctx.DoubleType()
p.c128Type = ctx.StructType([]llvm.Type{f64, f64}, false)
}
return p.c128Type
}
// NewPackage creates a new package. // NewPackage creates a new package.
func (p Program) NewPackage(name, pkgPath string) Package { func (p Program) NewPackage(name, pkgPath string) Package {
mod := p.ctx.NewModule(pkgPath) mod := p.ctx.NewModule(pkgPath)
@@ -394,24 +415,6 @@ func (p Program) String() Type {
return p.stringTy return p.stringTy
} }
/*
// AnyPtrPtr returns **any type.
func (p Program) AnyPtrPtr() Type {
if p.anyPPtr == nil {
p.anyPPtr = p.Pointer(p.AnyPtr())
}
return p.anyPPtr
}
// AnyPtr returns *any type.
func (p Program) AnyPtr() Type {
if p.anyPtr == nil {
p.anyPtr = p.Pointer(p.Any())
}
return p.anyPtr
}
*/
// Any returns the any (empty interface) type. // Any returns the any (empty interface) type.
func (p Program) Any() Type { func (p Program) Any() Type {
if p.anyTy == nil { if p.anyTy == nil {
@@ -484,6 +487,22 @@ func (p Program) Float32() Type {
return p.f32Ty return p.f32Ty
} }
// Complex128 returns complex128 type.
func (p Program) Complex128() Type {
if p.c128Ty == nil {
p.c128Ty = p.rawType(types.Typ[types.Complex128])
}
return p.c128Ty
}
// Complex64 returns complex64 type.
func (p Program) Complex64() Type {
if p.c64Ty == nil {
p.c64Ty = p.rawType(types.Typ[types.Complex64])
}
return p.c64Ty
}
// Byte returns byte type. // Byte returns byte type.
func (p Program) Byte() Type { func (p Program) Byte() Type {
if p.byteTy == nil { if p.byteTy == nil {

View File

@@ -214,6 +214,14 @@ func (p Program) Field(typ Type, i int) Type {
switch t := typ.raw.Type.(type) { switch t := typ.raw.Type.(type) {
case *types.Tuple: case *types.Tuple:
fld = t.At(i) fld = t.At(i)
case *types.Basic:
switch t.Kind() {
case types.Complex128:
return p.Float64()
case types.Complex64:
return p.Float32()
}
panic("Field: basic type doesn't have fields")
default: default:
fld = t.Underlying().(*types.Struct).Field(i) fld = t.Underlying().(*types.Struct).Field(i)
} }
@@ -330,7 +338,9 @@ func (p Program) toType(raw types.Type) Type {
case types.Float64: case types.Float64:
return &aType{p.ctx.DoubleType(), typ, vkFloat} return &aType{p.ctx.DoubleType(), typ, vkFloat}
case types.Complex64: case types.Complex64:
return &aType{p.tyComplex64(), typ, vkComplex}
case types.Complex128: case types.Complex128:
return &aType{p.tyComplex128(), typ, vkComplex}
case types.String: case types.String:
return &aType{p.rtString(), typ, vkString} return &aType{p.rtString(), typ, vkString}
case types.UnsafePointer: case types.UnsafePointer: