func (i I128) IntoBigInt(b *big.Int) {
	neg := i.hi&signBit != 0
	if i.hi > 0 {
		b.SetUint64(i.hi)
		b.Lsh(b, 64)
	}
	var lo big.Int
	lo.SetUint64(i.lo)
	b.Add(b, &lo)
	if neg {
		b.Xor(b, maxBigU128).Add(b, big1).Neg(b)
	}
}
IntoBigInt copies this I128 into a big.Int, allowing you to retain and
recycle memory.
package num
import (
	"fmt"
	"math/big"
	"math/bits"
)
const (
	signBit = 0x8000000000000000
)
type I128 struct {
	hi uint64
	lo uint64
}
func I128FromRaw(hi, lo uint64) I128 { return I128{hi: hi, lo: lo} }
func I128From64(v int64) (out I128) {
	var hi uint64
	if v < 0 {
		hi = maxUint64
	}
	return I128{hi: hi, lo: uint64(v)}
}
func I128From32(v int32) I128   { return I128From64(int64(v)) }
func I128From16(v int16) I128   { return I128From64(int64(v)) }
func I128From8(v int8) I128     { return I128From64(int64(v)) }
func I128FromInt(v int) I128    { return I128From64(int64(v)) }
func I128FromU64(v uint64) I128 { return I128{lo: v} }
func I128FromString(s string) (out I128, accurate bool, err error) {
	b, ok := new(big.Int).SetString(s, 10)
	if !ok {
		return out, false, fmt.Errorf("num: i128 string %q invalid", s)
	}
	out, accurate = I128FromBigInt(b)
	return out, accurate, nil
}
func MustI128FromString(s string) I128 {
	out, inRange, err := I128FromString(s)
	if err != nil {
		panic(err)
	}
	if !inRange {
		panic(fmt.Errorf("num: string %q was not in valid I128 range", s))
	}
	return out
}
var (
	minI128AsAbsU128 = U128{hi: 0x8000000000000000, lo: 0}
	maxI128AsU128    = U128{hi: 0x7FFFFFFFFFFFFFFF, lo: 0xFFFFFFFFFFFFFFFF}
)
func I128FromBigInt(v *big.Int) (out I128, accurate bool) {
	neg := v.Sign() < 0
	words := v.Bits()
	var u U128
	accurate = true
	switch intSize {
	case 64:
		lw := len(words)
		switch lw {
		case 0:
		case 1:
			u.lo = uint64(words[0])
		case 2:
			u.hi = uint64(words[1])
			u.lo = uint64(words[0])
		default:
			u, accurate = MaxU128, false
		}
	case 32:
		lw := len(words)
		switch lw {
		case 0:
		case 1:
			u.lo = uint64(words[0])
		case 2:
			u.lo = (uint64(words[1]) << 32) | (uint64(words[0]))
		case 3:
			u.hi = uint64(words[2])
			u.lo = (uint64(words[1]) << 32) | (uint64(words[0]))
		case 4:
			u.hi = (uint64(words[3]) << 32) | (uint64(words[2]))
			u.lo = (uint64(words[1]) << 32) | (uint64(words[0]))
		default:
			u, accurate = MaxU128, false
		}
	default:
		panic("num: unsupported bit size")
	}
	if !neg {
		if cmp := u.Cmp(maxI128AsU128); cmp == 0 {
			out = MaxI128
		} else if cmp > 0 {
			out, accurate = MaxI128, false
		} else {
			out = u.AsI128()
		}
	} else {
		if cmp := u.Cmp(minI128AsAbsU128); cmp == 0 {
			out = MinI128
		} else if cmp > 0 {
			out, accurate = MinI128, false
		} else {
			out = u.AsI128().Neg()
		}
	}
	return out, accurate
}
func MustI128FromBigInt(b *big.Int) I128 {
	out, inRange := I128FromBigInt(b)
	if !inRange {
		panic(fmt.Errorf("num: big.Int %d was not in valid I128 range", b))
	}
	return out
}
func I128FromFloat32(f float32) (out I128, inRange bool) {
	return I128FromFloat64(float64(f))
}
func MustI128FromFloat32(f float32) I128 {
	out, inRange := I128FromFloat32(f)
	if !inRange {
		panic(fmt.Errorf("num: float32 %f was not in valid I128 range", f))
	}
	return out
}
func I128FromFloat64(f float64) (out I128, inRange bool) {
	const spillPos = float64(maxUint64)  
	const spillNeg = -float64(maxUint64) - 1
	if f == 0 {
		return out, true
	} else if f != f {  
		return out, false
	} else if f < 0 {
		if f >= spillNeg {
			return I128{hi: maxUint64, lo: uint64(f)}, true
		} else if f >= minI128Float {
			f = -f
			lo := modpos(f, wrapUint64Float)  
			return I128{hi: ^uint64(f / wrapUint64Float), lo: ^uint64(lo)}, true
		} else {
			return MinI128, false
		}
	} else {
		if f <= spillPos {
			return I128{lo: uint64(f)}, true
		} else if f <= maxI128Float {
			lo := modpos(f, wrapUint64Float)  
			return I128{hi: uint64(f / wrapUint64Float), lo: uint64(lo)}, true
		} else {
			return MaxI128, false
		}
	}
}
func MustI128FromFloat64(f float64) I128 {
	out, inRange := I128FromFloat64(f)
	if !inRange {
		panic(fmt.Errorf("num: float64 %f was not in valid I128 range", f))
	}
	return out
}
func RandI128(source RandSource) (out I128) {
	return I128{hi: source.Uint64() & maxInt64, lo: source.Uint64()}
}
func (i I128) IsZero() bool { return i.lo == 0 && i.hi == 0 }
func (i I128) Raw() (hi uint64, lo uint64) { return i.hi, i.lo }
func (i I128) String() string {
	v := i.AsBigInt()
	return v.String()
}
func (i *I128) Scan(state fmt.ScanState, verb rune) error {
	t, err := state.Token(true, nil)
	if err != nil {
		return err
	}
	ts := string(t)
	v, inRange, err := I128FromString(ts)
	if err != nil {
		return err
	} else if !inRange {
		return fmt.Errorf("num: i128 value %q is not in range", ts)
	}
	*i = v
	return nil
}
func (i I128) Format(s fmt.State, c rune) {
	i.AsBigInt().Format(s, c)
}