Repository: goplus/gop
Pull request #1151 (2022-04-22 04:21:44)

add Int128


Patch:
diff --git a/builtin/ng/int128.go b/builtin/ng/int128.go
new file mode 100644
index 00000000..4180e566
--- /dev/null
+++ b/builtin/ng/int128.go
@@ -0,0 +1,542 @@
+package ng
+
+import (
+	"math/bits"
+)
+
+const (
+	signBit  = 0x8000000000000000
+	maxInt64 = 1<<63 - 1
+)
+
+type Int128 struct {
+	hi uint64
+	lo uint64
+}
+
+// Int128_Init: func int128.init(v int) int128
+func Int128_Init__0(v int) (out Int128) {
+	return Int128_Cast__1(int64(v))
+}
+
+// Int128_Cast: func int128(v int) int128
+func Int128_Cast__0(v int) Int128 {
+	return Int128_Cast__1(int64(v))
+}
+
+// Int128_Cast: func int128(v int64) int128
+func Int128_Cast__1(v int64) (out Int128) {
+	var hi uint64
+	if v < 0 {
+		hi = maxUint64
+	}
+	return Int128{hi: hi, lo: uint64(v)}
+}
+
+// Int128_Cast: func int128(v uint18) int128
+func Int128_Cast__2(v Uint128) (out Int128) {
+	return Int128{hi: v.hi, lo: v.lo}
+}
+
+// Int128_Cast: func int128(v uint64) int128
+func Int128_Cast__3(v uint64) Int128 {
+	return Int128{lo: v}
+}
+
+// Int128_Cast: func int128(v int32) int128
+func Int128_Cast__4(v int32) Int128 {
+	return Int128_Cast__1(int64(v))
+}
+
+// Int128_Cast: func int128(v int16) int128
+func Int128_Cast__5(v int16) Int128 {
+	return Int128_Cast__1(int64(v))
+}
+
+// Int128_Cast: func int128(v int8) int128
+func Int128_Cast__6(v int8) Int128 {
+	return Int128_Cast__1(int64(v))
+}
+
+// Gop_Rcast: func uint128(v int128) uint128
+func (i Int128) Gop_Rcast__0() Uint128 {
+	return Uint128{lo: i.lo, hi: i.hi}
+}
+
+// Gop_Rcast: func uint128(v int128) (uint128, bool)
+func (i Int128) Gop_Rcast__1() (out Uint128, inRange bool) {
+	return Uint128{lo: i.lo, hi: i.hi}, i.hi&signBit == 0
+}
+
+// Gop_Rcast: func int64(v int128) int64
+func (i Int128) Gop_Rcast__2() int64 {
+	if i.hi&signBit == 0 {
+		return int64(i.lo)
+	}
+	return -int64(^(i.lo - 1))
+}
+
+// Gop_Rcast: func int64(v int128) (int64, bool)
+func (i Int128) Gop_Rcast__3() (out int64, inRange bool) {
+	if i.hi&signBit == 0 {
+		return int64(i.lo), i.hi == 0 && i.lo <= maxInt64
+	}
+	return -int64(^(i.lo - 1)), i.hi == maxUint64 && i.lo >= 0x8000000000000000
+}
+
+// Gop_Rcast: func uint64(v int128) uint64
+func (i Int128) Gop_Rcast__4() uint64 {
+	return i.lo
+}
+
+// Gop_Rcast: func uint64(v int128) (uint64, bool)
+func (i Int128) Gop_Rcast__5() (out uint64, inRange bool) {
+	return i.lo, i.hi == 0
+}
+
+func (i Int128) IsZero() bool {
+	return i.lo == 0 && i.hi == 0
+}
+
+func (i Int128) Sign() int {
+	if i.lo == 0 && i.hi == 0 {
+		return 0
+	} else if i.hi&signBit == 0 {
+		return 1
+	}
+	return -1
+}
+
+func (i Int128) Gop_Inc() (v Int128) {
+	v.lo = i.lo + 1
+	v.hi = i.hi
+	if i.lo > v.lo {
+		v.hi++
+	}
+	return v
+}
+
+func (i Int128) Gop_Dec() (v Int128) {
+	v.lo = i.lo - 1
+	v.hi = i.hi
+	if i.lo < v.lo {
+		v.hi--
+	}
+	return v
+}
+
+func (i Int128) Gop_Add__1(n Int128) (v Int128) {
+	var carry uint64
+	v.lo, carry = bits.Add64(i.lo, n.lo, 0)
+	v.hi, _ = bits.Add64(i.hi, n.hi, carry)
+	return v
+}
+
+func (i Int128) Gop_Add__0(n int64) (v Int128) {
+	var carry uint64
+	v.lo, carry = bits.Add64(i.lo, uint64(n), 0)
+	if n < 0 {
+		v.hi = i.hi + maxUint64 + carry
+	} else {
+		v.hi = i.hi + carry
+	}
+	return v
+}
+
+func (i Int128) Gop_Sub__1(n Int128) (v Int128) {
+	var borrowed uint64
+	v.lo, borrowed = bits.Sub64(i.lo, n.lo, 0)
+	v.hi, _ = bits.Sub64(i.hi, n.hi, borrowed)
+	return v
+}
+
+func (i Int128) Gop_Sub__0(n int64) (v Int128) {
+	var borrowed uint64
+	if n < 0 {
+		v.lo, borrowed = bits.Sub64(i.lo, uint64(n), 0)
+		v.hi = i.hi - maxUint64 - borrowed
+	} else {
+		v.lo, borrowed = bits.Sub64(i.lo, uint64(n), 0)
+		v.hi = i.hi - borrowed
+	}
+	return v
+}
+
+func (i Int128) Gop_Neg() (v Int128) {
+	if i.lo == 0 && i.hi == 0 {
+		return
+	}
+	if i.hi&signBit == 0 {
+		v.hi = ^i.hi
+		v.lo = (^i.lo) + 1
+	} else {
+		v.hi = ^i.hi
+		v.lo = ^(i.lo - 1)
+	}
+	if v.lo == 0 { // handle overflow
+		v.hi++
+	}
+	return v
+}
+
+// Abs returns the absolute value of i as a signed integer.
+func (i Int128) Abs__0() Int128 {
+	if i.hi&signBit != 0 {
+		i.hi = ^i.hi
+		i.lo = ^(i.lo - 1)
+		if i.lo == 0 { // handle carry
+			i.hi++
+		}
+	}
+	return i
+}
+
+func (i Int128) Abs__1() (ret Int128, inRange bool) {
+	return i.Abs__0(), i.hi != 0x8000000000000000 || i.lo != 0
+}
+
+// AbsU returns the absolute value of i as an unsigned integer. All
+// values of i are representable using this function, but the type is
+// changed.
+func (i Int128) AbsU() Uint128 {
+	if i.hi == 0x8000000000000000 && i.lo == 0 {
+		return Uint128{hi: 0x8000000000000000}
+	}
+	if i.hi&signBit != 0 {
+		i.hi = ^i.hi
+		i.lo = ^(i.lo - 1)
+		if i.lo == 0 { // handle carry
+			i.hi++
+		}
+	}
+	return Uint128{hi: i.hi, lo: i.lo}
+}
+
+// Cmp compares i to n and returns:
+//
+//	< 0 if i <  n
+//	  0 if i == n
+//	> 0 if i >  n
+//
+// The specific value returned by Cmp is undefined, but it is guaranteed to
+// satisfy the above constraints.
+func (i Int128) Cmp__1(n Int128) int {
+	if i.hi == n.hi && i.lo == n.lo {
+		return 0
+	} else if i.hi&signBit == n.hi&signBit {
+		if i.hi > n.hi || (i.hi == n.hi && i.lo > n.lo) {
+			return 1
+		}
+	} else if i.hi&signBit == 0 {
+		return 1
+	}
+	return -1
+}
+
+// Cmp64 compares 'i' to 64-bit int 'n' and returns:
+//
+//	< 0 if i <  n
+//	  0 if i == n
+//	> 0 if i >  n
+//
+// The specific value returned by Cmp is undefined, but it is guaranteed to
+// satisfy the above constraints.
+func (i Int128) Cmp__0(n int64) int {
+	var nhi uint64
+	var nlo = uint64(n)
+	if n < 0 {
+		nhi = maxUint64
+	}
+	if i.hi == nhi && i.lo == nlo {
+		return 0
+	} else if i.hi&signBit == nhi&signBit {
+		if i.hi > nhi || (i.hi == nhi && i.lo > nlo) {
+			return 1
+		}
+	} else if i.hi&signBit == 0 {
+		return 1
+	}
+	return -1
+}
+
+func (i Int128) Gop_EQ__1(n Int128) bool {
+	return i.hi == n.hi && i.lo == n.lo
+}
+
+func (i Int128) Gop_EQ__0(n int64) bool {
+	var nhi uint64
+	var nlo = uint64(n)
+	if n < 0 {
+		nhi = maxUint64
+	}
+	return i.hi == nhi && i.lo == nlo
+}
+
+func (i Int128) Gop_GT__1(n Int128) bool {
+	if i.hi&signBit == n.hi&signBit {
+		return i.hi > n.hi || (i.hi == n.hi && i.lo > n.lo)
+	} else if i.hi&signBit == 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_GT__0(n int64) bool {
+	var nhi uint64
+	var nlo = uint64(n)
+	if n < 0 {
+		nhi = maxUint64
+	}
+
+	if i.hi&signBit == nhi&signBit {
+		return i.hi > nhi || (i.hi == nhi && i.lo > nlo)
+	} else if i.hi&signBit == 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_GE__1(n Int128) bool {
+	if i.hi == n.hi && i.lo == n.lo {
+		return true
+	}
+	if i.hi&signBit == n.hi&signBit {
+		return i.hi > n.hi || (i.hi == n.hi && i.lo > n.lo)
+	} else if i.hi&signBit == 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_GE__0(n int64) bool {
+	var nhi uint64
+	var nlo = uint64(n)
+	if n < 0 {
+		nhi = maxUint64
+	}
+
+	if i.hi == nhi && i.lo == nlo {
+		return true
+	}
+	if i.hi&signBit == nhi&signBit {
+		return i.hi > nhi || (i.hi == nhi && i.lo > nlo)
+	} else if i.hi&signBit == 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_LT__1(n Int128) bool {
+	if i.hi&signBit == n.hi&signBit {
+		return i.hi < n.hi || (i.hi == n.hi && i.lo < n.lo)
+	} else if i.hi&signBit != 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_LT__0(n int64) bool {
+	var nhi uint64
+	var nlo = uint64(n)
+	if n < 0 {
+		nhi = maxUint64
+	}
+
+	if i.hi&signBit == nhi&signBit {
+		return i.hi < nhi || (i.hi == nhi && i.lo < nlo)
+	} else if i.hi&signBit != 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_LE__1(n Int128) bool {
+	if i.hi == n.hi && i.lo == n.lo {
+		return true
+	}
+	if i.hi&signBit == n.hi&signBit {
+		return i.hi < n.hi || (i.hi == n.hi && i.lo < n.lo)
+	} else if i.hi&signBit != 0 {
+		return true
+	}
+	return false
+}
+
+func (i Int128) Gop_LE__0(n int64) bool {
+	var nhi uint64
+	var nlo = uint64(n)
+	if n < 0 {
+		nhi = maxUint64
+	}
+
+	if i.hi == nhi && i.lo == nlo {
+		return true
+	}
+	if i.hi&signBit == nhi&signBit {
+		return i.hi < nhi || (i.hi == nhi && i.lo < nlo)
+	} else if i.hi&signBit != 0 {
+		return true
+	}
+	return false
+}
+
+// Mul returns the product of two I128s.
+//
+// Overflow should wrap around, as per the Go spec.
+//
+func (i Int128) Gop_Mul__1(n Int128) (dest Int128) {
+	hi, lo := bits.Mul64(i.lo, n.lo)
+	hi += i.hi*n.lo + i.lo*n.hi
+	return Int128{hi, lo}
+}
+
+func (i Int128) Gop_Mul__0(n int64) Int128 {
+	nlo := uint64(n)
+	var nhi uint64
+	if n < 0 {
+		nhi = maxUint64
+	}
+	hi, lo := bits.Mul64(i.lo, nlo)
+	hi += i.hi*nlo + i.lo*nhi
+	return Int128{hi, lo}
+}
+
+// QuoRem returns the quotient q and remainder r for y != 0. If y == 0, a
+// division-by-zero run-time panic occurs.
+//
+// QuoRem implements T-division and modulus (like Go):
+//
+//	q = x/y      with the result truncated to zero
+//	r = x - y*q
+//
+// U128 does not support big.Int.DivMod()-style Euclidean division.
+//
+// Note: dividing MinI128 by -1 will overflow, returning MinI128, as
+// per the Go spec (https://golang.org/ref/spec#Integer_operators):
+//
+//	The one exception to this rule is that if the dividend x is the most
+//	negative value for the int type of x, the quotient q = x / -1 is equal to x
+//	(and r = 0) due to two's-complement integer overflow.
+func (i Int128) QuoRem__1(by Int128) (q, r Int128) {
+	qSign, rSign := 1, 1
+	if i.Gop_LT__0(0) {
+		qSign, rSign = -1, -1
+		i = i.Gop_Neg()
+	}
+	if by.Gop_LT__0(0) {
+		qSign = -qSign
+		by = by.Gop_Neg()
+	}
+
+	qu, ru := i.Gop_Rcast__0().QuoRem__1(by.Gop_Rcast__0())
+	q, r = Int128_Cast__2(qu), Int128_Cast__2(ru)
+	if qSign < 0 {
+		q = q.Gop_Neg()
+	}
+	if rSign < 0 {
+		r = r.Gop_Neg()
+	}
+	return q, r
+}
+
+func (i Int128) QuoRem__0(by int64) (q, r Int128) {
+	ineg := i.hi&signBit != 0
+	if ineg {
+		i = i.Gop_Neg()
+	}
+	byneg := by < 0
+	if byneg {
+		by = -by
+	}
+
+	n := uint64(by)
+	if i.hi < n {
+		q.lo, r.lo = bits.Div64(i.hi, i.lo, n)
+	} else {
+		q.hi, r.lo = bits.Div64(0, i.hi, n)
+		q.lo, r.lo = bits.Div64(r.lo, i.lo, n)
+	}
+	if ineg != byneg {
+		q = q.Gop_Neg()
+	}
+	if ineg {
+		r = r.Gop_Neg()
+	}
+	return q, r
+}
+
+// Quo returns the quotient x/y for y != 0. If y == 0, a division-by-zero
+// run-time panic occurs. Quo implements truncated division (like Go); see
+// QuoRem for more details.
+func (i Int128) Gop_Quo__1(by Int128) (q Int128) {
+	qSign := 1
+	if i.Gop_LT__0(0) {
+		qSign = -1
+		i = i.Gop_Neg()
+	}
+	if by.Gop_LT__0(0) {
+		qSign = -qSign
+		by = by.Gop_Neg()
+	}
+
+	qu := i.Gop_Rcast__0().Gop_Quo__1(by.Gop_Rcast__0())
+	q = Int128_Cast__2(qu)
+	if qSign < 0 {
+		q = q.Gop_Neg()
+	}
+	return q
+}
+
+func (i Int128) Gop_Quo__0(by int64) (q Int128) {
+	ineg := i.hi&signBit != 0
+	if ineg {
+		i = i.Gop_Neg()
+	}
+	byneg := by < 0
+	if byneg {
+		by = -by
+	}
+
+	n := uint64(by)
+	if i.hi < n {
+		q.lo, _ = bits.Div64(i.hi, i.lo, n)
+	} else {
+		var rlo uint64
+		q.hi, rlo = bits.Div64(0, i.hi, n)
+		q.lo, _ = bits.Div64(rlo, i.lo, n)
+	}
+	if ineg != byneg {
+		q = q.Gop_Neg()
+	}
+	return q
+}
+
+// Rem returns the remainder of x%y for y != 0. If y == 0, a division-by-zero
+// run-time panic occurs. Rem implements truncated modulus (like Go); see
+// QuoRem for more details.
+func (i Int128) Rem__1(by Int128) (r Int128) {
+	_, r = i.QuoRem__1(by)
+	return r
+}
+
+func (i Int128) Rem__0(by int64) (r Int128) {
+	ineg := i.hi&signBit != 0
+	if ineg {
+		i = i.Gop_Neg()
+	}
+	if by < 0 {
+		by = -by
+	}
+
+	n := uint64(by)
+	if i.hi < n {
+		_, r.lo = bits.Div64(i.hi, i.lo, n)
+	} else {
+		_, r.lo = bits.Div64(0, i.hi, n)
+		_, r.lo = bits.Div64(r.lo, i.lo, n)
+	}
+	if ineg {
+		r = r.Gop_Neg()
+	}
+	return r
+}
diff --git a/builtin/ng/uint128.go b/builtin/ng/uint128.go
index 0f8520f7..4fdfd8a0 100644
--- a/builtin/ng/uint128.go
+++ b/builtin/ng/uint128.go
@@ -8,6 +8,10 @@ const (
 	GopPackage = true // to indicate this is a Go+ package
 )
 
+const (
+	maxUint64 = (1 << 64) - 1
+)
+
 type Gop_ninteger = uint
 
 type Uint128 struct {
@@ -22,11 +26,6 @@ func Uint128_Init__0(v int) (out Uint128) {
 	return Uint128{lo: uint64(v)}
 }
 
-// Uint128_Cast: func uint128.init(v uint64) uint128
-func Uint128_Init__1(v uint64) Uint128 {
-	return Uint128{lo: v}
-}
-
 // Uint128_Cast: func uint128(hi, lo uint64) uint128
 func Uint128_Cast__0(hi, lo uint64) Uint128 {
 	return Uint128{hi: hi, lo: lo}
@@ -60,7 +59,7 @@ func Uint128_Cast__5(v uint8) Uint128 {
 // Uint128_Cast: func uint128(v int64) uint128
 func Uint128_Cast__6(v int64) (out Uint128) {
 	if v < 0 {
-		return Uint128{hi: ^uint64(0), lo: uint64(v)}
+		return Uint128{hi: maxUint64, lo: uint64(v)}
 	}
 	return Uint128{lo: uint64(v)}
 }
@@ -178,7 +177,7 @@ func (u Uint128) ReverseBytes() Uint128 {
 // The specific value returned by Cmp is undefined, but it is guaranteed to
 // satisfy the above constraints.
 //
-func (u Uint128) Cmp(n Uint128) int {
+func (u Uint128) Cmp__1(n Uint128) int {
 	if u.hi == n.hi {
 		if u.lo > n.lo {
 			return 1
@@ -195,7 +194,7 @@ func (u Uint128) Cmp(n Uint128) int {
 	return 0
 }
 
-func (u Uint128) Cmp64(n uint64) int {
+func (u Uint128) Cmp__0(n uint64) int {
 	if u.hi > 0 || u.lo > n {
 		return 1
 	} else if u.lo < n {
@@ -218,81 +217,81 @@ func (u Uint128) Gop_Dec() (v Uint128) {
 	return v
 }
 
-func (u Uint128) Gop_Add__0(n Uint128) (v Uint128) {
+func (u Uint128) Gop_Add__1(n Uint128) (v Uint128) {
 	var carry uint64
 	v.lo, carry = bits.Add64(u.lo, n.lo, 0)
 	v.hi, _ = bits.Add64(u.hi, n.hi, carry)
 	return v
 }
 
-func (u Uint128) Gop_Add__1(n uint64) (v Uint128) {
+func (u Uint128) Gop_Add__0(n uint64) (v Uint128) {
 	var carry uint64
 	v.lo, carry = bits.Add64(u.lo, n, 0)
 	v.hi = u.hi + carry
 	return v
 }
 
-func (u Uint128) Gop_Sub__0(n Uint128) (v Uint128) {
+func (u Uint128) Gop_Sub__1(n Uint128) (v Uint128) {
 	var borrowed uint64
 	v.lo, borrowed = bits.Sub64(u.lo, n.lo, 0)
 	v.hi, _ = bits.Sub64(u.hi, n.hi, borrowed)
 	return v
 }
 
-func (u Uint128) Gop_Sub__1(n uint64) (v Uint128) {
+func (u Uint128) Gop_Sub__0(n uint64) (v Uint128) {
 	var borrowed uint64
 	v.lo, borrowed = bits.Sub64(u.lo, n, 0)
 	v.hi = u.hi - borrowed
 	return v
 }
 
-func (u Uint128) Gop_EQ__0(n Uint128) bool {
+func (u Uint128) Gop_EQ__1(n Uint128) bool {
 	return u.hi == n.hi && u.lo == n.lo
 }
 
-func (u Uint128) Gop_EQ__1(n uint64) bool {
+func (u Uint128) Gop_EQ__0(n uint64) bool {
 	return u.hi == 0 && u.lo == n
 }
 
-func (u Uint128) Gop_GT__0(n Uint128) bool {
+func (u Uint128) Gop_GT__1(n Uint128) bool {
 	return u.hi > n.hi || (u.hi == n.hi && u.lo > n.lo)
 }
 
-func (u Uint128) Gop_GT__1(n uint64) bool {
+func (u Uint128) Gop_GT__0(n uint64) bool {
 	return u.hi > 0 || u.lo > n
 }
 
-func (u Uint128) Gop_GE__0(n Uint128) bool {
+func (u Uint128) Gop_GE__1(n Uint128) bool {
 	return u.hi > n.hi || (u.hi == n.hi && u.lo >= n.lo)
 }
 
-func (u Uint128) Gop_GE__1(n uint64) bool {
+func (u Uint128) Gop_GE__0(n uint64) bool {
 	return u.hi > 0 || u.lo >= n
 }
 
-func (u Uint128) Gop_LT__0(n Uint128) bool {
+func (u Uint128) Gop_LT__1(n Uint128) bool {
 	return u.hi < n.hi || (u.hi == n.hi && u.lo < n.lo)
 }
 
-func (u Uint128) Gop_LT__1(n uint64) bool {
+func (u Uint128) Gop_LT__0(n uint64) bool {
 	return u.hi == 0 && u.lo < n
 }
 
-func (u Uint128) Gop_LE__0(n Uint128) bool {
+func (u Uint128) Gop_LE__1(n Uint128) bool {
 	return u.hi < n.hi || (u.hi == n.hi && u.lo <= n.lo)
 }
 
-func (u Uint128) Gop_LE__1(n uint64) bool {
+func (u Uint128) Gop_LE__0(n uint64) bool {
 	return u.hi == 0 && u.lo <= n
 }
 
-func (u Uint128) Gop_And__0(n Uint128) Uint128 {
+func (u Uint128) Gop_And__1(n Uint128) Uint128 {
 	u.hi = u.hi & n.hi
 	u.lo = u.lo & n.lo
 	return u
 }
 
-func (u Uint128) Gop_And__1(n uint64) Uint128 {
+func (u Uint128) Gop_And__0(n uint64) Uint128 {
 	return Uint128{lo: u.lo & n}
 }
 
@@ -308,24 +307,24 @@ func (u Uint128) Gop_Not() (out Uint128) {
 	return out
 }
 
-func (u Uint128) Gop_Or__0(n Uint128) (out Uint128) {
+func (u Uint128) Gop_Or__1(n Uint128) (out Uint128) {
 	out.hi = u.hi | n.hi
 	out.lo = u.lo | n.lo
 	return out
 }
 
-func (u Uint128) Gop_Or__1(n uint64) Uint128 {
+func (u Uint128) Gop_Or__0(n uint64) Uint128 {
 	u.lo = u.lo | n
 	return u
 }
 
-func (u Uint128) Gop_Xor__0(v Uint128) Uint128 {
+func (u Uint128) Gop_Xor__1(v Uint128) Uint128 {
 	u.hi = u.hi ^ v.hi
 	u.lo = u.lo ^ v.lo
 	return u
 }
 
-func (u Uint128) Gop_Xor__1(v uint64) Uint128 {
+func (u Uint128) Gop_Xor__0(v uint64) Uint128 {
 	u.hi = u.hi ^ 0
 	u.lo = u.lo ^ v
 	return u
@@ -364,13 +363,13 @@ func (u Uint128) Gop_Rsh(n Gop_ninteger) (v Uint128) {
 	return v
 }
 
-func (u Uint128) Gop_Mul__0(n Uint128) Uint128 {
+func (u Uint128) Gop_Mul__1(n Uint128) Uint128 {
 	hi, lo := bits.Mul64(u.lo, n.lo)
 	hi += u.hi*n.lo + u.lo*n.hi
 	return Uint128{hi, lo}
 }
 
-func (u Uint128) Gop_Mul__1(n uint64) (dest Uint128) {
+func (u Uint128) Gop_Mul__0(n uint64) (dest Uint128) {
 	dest.hi, dest.lo = bits.Mul64(u.lo, n)
 	dest.hi += u.hi * n
 	return dest
@@ -380,7 +379,7 @@ const (
 	divAlgoLeading0Spill = 16
 )
 
-func (u Uint128) Gop_Quo__0(by Uint128) (q Uint128) {
+func (u Uint128) Gop_Quo__1(by Uint128) (q Uint128) {
 	if by.lo == 0 && by.hi == 0 {
 		panic("division by zero")
 	}
@@ -408,7 +407,7 @@ func (u Uint128) Gop_Quo__0(by Uint128) (q Uint128) {
 		return u.Gop_Rsh(byTrailing0)
 	}
 
-	if cmp := u.Cmp(by); cmp < 0 {
+	if cmp := u.Cmp__1(by); cmp < 0 {
 		return q // it's 100% remainder
 	} else if cmp == 0 {
 		q.lo = 1 // dividend and divisor are the same
@@ -424,7 +423,7 @@ func (u Uint128) Gop_Quo__0(by Uint128) (q Uint128) {
 	}
 }
 
-func (u Uint128) Gop_Quo__1(by uint64) (q Uint128) {
+func (u Uint128) Gop_Quo__0(by uint64) (q Uint128) {
 	if u.hi < by {
 		q.lo, _ = bits.Div64(u.hi, u.lo, by)
 	} else {
@@ -434,7 +433,7 @@ func (u Uint128) Gop_Quo__1(by uint64) (q Uint128) {
 	return q
 }
 
-func (u Uint128) QuoRem(by Uint128) (q, r Uint128) {
+func (u Uint128) QuoRem__1(by Uint128) (q, r Uint128) {
 	if by.lo == 0 && by.hi == 0 {
 		panic("division by zero")
 	}
@@ -462,11 +461,11 @@ func (u Uint128) QuoRem(by Uint128) (q, r Uint128) {
 	if (byLeading0 + byTrailing0) == 127 {
 		q = u.Gop_Rsh(byTrailing0)
 		by = by.Gop_Dec()
-		r = by.Gop_And__0(u)
+		r = by.Gop_And__1(u)
 		return
 	}
 
-	if cmp := u.Cmp(by); cmp < 0 {
+	if cmp := u.Cmp__1(by); cmp < 0 {
 		return q, u // it's 100% remainder
 
 	} else if cmp == 0 {
@@ -482,7 +481,7 @@ func (u Uint128) QuoRem(by Uint128) (q, r Uint128) {
 	}
 }
 
-func (u Uint128) QuoRem64(by uint64) (q, r Uint128) {
+func (u Uint128) QuoRem__0(by uint64) (q, r Uint128) {
 	if u.hi < by {
 		q.lo, r.lo = bits.Div64(u.hi, u.lo, by)
 	} else {
@@ -493,13 +492,13 @@ func (u Uint128) QuoRem64(by uint64) (q, r Uint128) {
 }
 
 // Gop_Rem: func (a uint128) % (b uint128) uint128
-func (u Uint128) Gop_Rem__0(by Uint128) (r Uint128) {
+func (u Uint128) Gop_Rem__1(by Uint128) (r Uint128) {
 	// TODO: inline only the needed bits
-	_, r = u.QuoRem(by)
+	_, r = u.QuoRem__1(by)
 	return r
 }
 
-func (u Uint128) Gop_Rem__1(by uint64) (r Uint128) {
+func (u Uint128) Gop_Rem__0(by uint64) (r Uint128) {
 	// https://github.com/golang/go/issues/28970
 	// if u.hi < by {
 	//     _, r.lo = bits.Rem64(u.hi, u.lo, by)
@@ -662,12 +661,12 @@ func quorem128by128(m, v Uint128, vHiLeading0, vLoLeading0 uint) (q, r Uint128)
 			q1 = q1.Gop_Dec()
 		}
 		q = q1
-		q1 = q1.Gop_Mul__0(v)
-		r = m.Gop_Sub__0(q1)
+		q1 = q1.Gop_Mul__1(v)
+		r = m.Gop_Sub__1(q1)
 
-		if r.Cmp(v) >= 0 {
+		if r.Cmp__1(v) >= 0 {
 			q = q.Gop_Inc()
-			r = r.Gop_Sub__0(v)
+			r = r.Gop_Sub__1(v)
 		}
 
 		return q, r
@@ -685,7 +684,7 @@ func quorem128bin(u, by Uint128, uLeading0, byLeading0 uint) (q, r Uint128) {
 
 		// performance tweak: simulate greater than or equal by hand-inlining "not less than".
 		if u.hi > by.hi || (u.hi == by.hi && u.lo >= by.lo) {
-			u = u.Gop_Sub__0(by)
+			u = u.Gop_Sub__1(by)
 			q.lo |= 1
 		}
 
@@ -714,7 +713,7 @@ func quo128bin(u, by Uint128, uLeading0, byLeading0 uint) (q Uint128) {
 
 		// u >= by
 		if u.hi > by.hi || (u.hi == by.hi && u.lo >= by.lo) {
-			u = u.Gop_Sub__0(by)
+			u = u.Gop_Sub__1(by)
 			q.lo |= 1
 		}
 
diff --git a/cl/builtin.go b/cl/builtin.go
index 150a5ae7..8d4cbf59 100644
--- a/cl/builtin.go
+++ b/cl/builtin.go
@@ -50,6 +50,7 @@ func initBuiltin(pkg gox.PkgImporter, builtin *types.Package, fmt, big, ng, buil
 	}
 	scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "newRange", buil.Ref("NewRange__0")))
 	scope.Insert(types.NewTypeName(token.NoPos, builtin, "uint128", ng.Ref("Uint128").Type()))
+	scope.Insert(types.NewTypeName(token.NoPos, builtin, "int128", ng.Ref("Int128").Type()))
 	scope.Insert(types.NewTypeName(token.NoPos, builtin, "any", gox.TyEmptyInterface))
 }
 


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index 125c8504..e272dcd3 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -1201,7 +1201,20 @@ var z uint128 = x + y
 import ng "github.com/goplus/gop/builtin/ng"
 
 var x, y ng.Uint128
-var z ng.Uint128 = x.Gop_Add__0(y)
+var z ng.Uint128 = x.Gop_Add__1(y)
+`)
+}
+
+func TestInt128Add(t *testing.T) {
+	gopClTest(t, `
+var x, y int128
+var z int128 = x + y
+`, `package main
+
+import ng "github.com/goplus/gop/builtin/ng"
+
+var x, y ng.Int128
+var z ng.Int128 = x.Gop_Add__1(y)
 `)
 }
 
@@ -1243,6 +1256,17 @@ var x ng.Uint128 = ng.Uint128_Init__0(1)
 `)
 }
 
+func TestInt128Lit(t *testing.T) {
+	gopClTest(t, `
+var x int128 = 1
+`, `package main
+
+import ng "github.com/goplus/gop/builtin/ng"
+
+var x ng.Int128 = ng.Int128_Init__0(1)
+`)
+}
+
 func TestBigRatLit(t *testing.T) {
 	gopClTest(t, `
 var x = 1/2r