github.com/richardwilkes/toolbox@v1.121.0/xmath/num/int128.go (about)

     1  // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, version 2.0. If a copy of the MPL was not distributed with
     5  // this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  //
     7  // This Source Code Form is "Incompatible With Secondary Licenses", as
     8  // defined by the Mozilla Public License, version 2.0.
     9  
    10  package num
    11  
    12  import (
    13  	"fmt"
    14  	"math"
    15  	"math/big"
    16  	"math/bits"
    17  	"strconv"
    18  
    19  	"github.com/richardwilkes/toolbox/errs"
    20  )
    21  
    22  const (
    23  	signBit        = 0x8000000000000000
    24  	minInt128Float = float64(-170141183460469231731687303715884105728)
    25  	maxInt128Float = float64(170141183460469231731687303715884105727)
    26  )
    27  
    28  var (
    29  	// MaxInt128 is the maximum value representable by an Int128.
    30  	MaxInt128 = Int128{hi: 0x7FFFFFFFFFFFFFFF, lo: 0xFFFFFFFFFFFFFFFF}
    31  	// MinInt128 is the minimum value representable by an Int128.
    32  	MinInt128 = Int128{hi: signBit, lo: 0}
    33  )
    34  
    35  var (
    36  	minInt128AsAbsUint128 = Uint128{hi: signBit, lo: 0}
    37  	maxInt128AsUint128    = Uint128{hi: 0x7FFFFFFFFFFFFFFF, lo: 0xFFFFFFFFFFFFFFFF}
    38  	maxBigUint128, _      = new(big.Int).SetString("340282366920938463463374607431768211455", 10)
    39  	big1                  = new(big.Int).SetInt64(1)
    40  )
    41  
    42  // Int128 represents a signed 128-bit integer.
    43  type Int128 struct {
    44  	hi uint64
    45  	lo uint64
    46  }
    47  
    48  // Int128From64 creates an Int128 from an int64 value.
    49  func Int128From64(v int64) Int128 {
    50  	var hi uint64
    51  	if v < 0 {
    52  		hi = math.MaxUint64
    53  	}
    54  	return Int128{hi: hi, lo: uint64(v)}
    55  }
    56  
    57  // Int128FromUint64 creates an Int128 from a uint64 value.
    58  func Int128FromUint64(v uint64) Int128 {
    59  	return Int128{lo: v}
    60  }
    61  
    62  // Int128FromFloat64 creates an Int128 from a float64 value.
    63  func Int128FromFloat64(f float64) Int128 {
    64  	switch {
    65  	case f == 0 || f != f: // 0 or NaN
    66  		return Int128{}
    67  	case f < 0:
    68  		switch {
    69  		case f >= -float64(math.MaxUint64)-1:
    70  			return Int128{
    71  				hi: math.MaxUint64,
    72  				lo: uint64(f),
    73  			}
    74  		case f >= minInt128Float:
    75  			f = -f
    76  			lo := math.Mod(f, wrapUint64Float)
    77  			return Int128{
    78  				hi: ^uint64(f / wrapUint64Float),
    79  				lo: ^uint64(lo),
    80  			}
    81  		default:
    82  			return MinInt128
    83  		}
    84  	default:
    85  		switch {
    86  		case f <= float64(math.MaxUint64):
    87  			return Int128{lo: uint64(f)}
    88  		case f <= maxInt128Float:
    89  			return Int128{
    90  				hi: uint64(f / wrapUint64Float),
    91  				lo: uint64(math.Mod(f, wrapUint64Float)),
    92  			}
    93  		default:
    94  			return MaxInt128
    95  		}
    96  	}
    97  }
    98  
    99  // Int128FromBigInt creates an Int128 from a big.Int.
   100  func Int128FromBigInt(v *big.Int) Int128 {
   101  	var i Uint128
   102  	words := v.Bits()
   103  	switch len(words) {
   104  	case 0:
   105  	case 1:
   106  		i.lo = uint64(words[0])
   107  	case 2:
   108  		if intSize == 64 {
   109  			i.hi = uint64(words[1])
   110  			i.lo = uint64(words[0])
   111  		} else {
   112  			i.lo = (uint64(words[1]) << 32) | (uint64(words[0]))
   113  		}
   114  	case 3:
   115  		if intSize == 64 {
   116  			i = MaxUint128
   117  		} else {
   118  			i.hi = uint64(words[2])
   119  			i.lo = (uint64(words[1]) << 32) | (uint64(words[0]))
   120  		}
   121  	case 4:
   122  		if intSize == 64 {
   123  			i = MaxUint128
   124  		} else {
   125  			i.hi = (uint64(words[3]) << 32) | (uint64(words[2]))
   126  			i.lo = (uint64(words[1]) << 32) | (uint64(words[0]))
   127  		}
   128  	default:
   129  		i = MaxUint128
   130  	}
   131  	if v.Sign() >= 0 {
   132  		if i.LessThan(maxInt128AsUint128) {
   133  			return i.AsInt128()
   134  		}
   135  		return MaxInt128
   136  	}
   137  	if i.LessThan(minInt128AsAbsUint128) {
   138  		return i.AsInt128().Neg()
   139  	}
   140  	return MinInt128
   141  }
   142  
   143  // Int128FromString creates an Int128 from a string.
   144  func Int128FromString(s string) (Int128, error) {
   145  	b, err := parseToBigInt(s)
   146  	if err != nil {
   147  		return Int128{}, err
   148  	}
   149  	return Int128FromBigInt(b), nil
   150  }
   151  
   152  // Int128FromStringNoCheck creates an Int128 from a string. Unlike Int128FromString, this allows any string as input.
   153  func Int128FromStringNoCheck(s string) Int128 {
   154  	i, _ := Int128FromString(s) //nolint:errcheck // Failure results in 0
   155  	return i
   156  }
   157  
   158  // Int128FromComponents creates an Int128 from two uint64 values representing the high and low bits.
   159  func Int128FromComponents(high, low uint64) Int128 {
   160  	return Int128{hi: high, lo: low}
   161  }
   162  
   163  // Int128FromRand generates a signed 128-bit random integer.
   164  func Int128FromRand(source RandomSource) Int128 {
   165  	return Int128{hi: source.Uint64(), lo: source.Uint64()}
   166  }
   167  
   168  // Components returns the two uint64 values representing the high and low bits.
   169  func (i Int128) Components() (high, low uint64) {
   170  	return i.hi, i.lo
   171  }
   172  
   173  // IsZero returns true if the value is 0.
   174  func (i Int128) IsZero() bool {
   175  	return i.hi|i.lo == 0
   176  }
   177  
   178  // ToBigInt stores the Int128's value into the specified big.Int.
   179  func (i Int128) ToBigInt(b *big.Int) {
   180  	Uint128(i).ToBigInt(b)
   181  	if !i.IsUint128() {
   182  		b.Xor(b, maxBigUint128).Add(b, big1).Neg(b)
   183  	}
   184  }
   185  
   186  // AsBigInt returns the Int128 as a big.Int.
   187  func (i Int128) AsBigInt() *big.Int {
   188  	var b big.Int
   189  	i.ToBigInt(&b)
   190  	return &b
   191  }
   192  
   193  // AsBigFloat returns the Int128 as a big.Float.
   194  func (i Int128) AsBigFloat() (b *big.Float) {
   195  	return new(big.Float).SetInt(i.AsBigInt())
   196  }
   197  
   198  // AsFloat64 returns the Int128 as a float64.
   199  func (i Int128) AsFloat64() float64 {
   200  	switch {
   201  	case i.hi == 0:
   202  		if i.lo == 0 {
   203  			return 0
   204  		}
   205  		return float64(i.lo)
   206  	case i.hi == math.MaxUint64:
   207  		return -float64((^i.lo) + 1)
   208  	case i.hi&signBit == 0:
   209  		return (float64(i.hi) * maxUint64Float) + float64(i.lo)
   210  	default:
   211  		return (-float64(^i.hi) * maxUint64Float) + -float64(^i.lo)
   212  	}
   213  }
   214  
   215  // IsUint128 returns true if this value can be represented as an Uint128 without any loss.
   216  func (i Int128) IsUint128() bool {
   217  	return i.hi&signBit == 0
   218  }
   219  
   220  // AsUint128 returns the Int128 as a Uint128.
   221  func (i Int128) AsUint128() Uint128 {
   222  	return Uint128(i)
   223  }
   224  
   225  // IsInt64 returns true if this value can be represented as an int64 without any loss.
   226  func (i Int128) IsInt64() bool {
   227  	if i.hi&signBit != 0 {
   228  		return i.hi == math.MaxUint64 && i.lo >= signBit
   229  	}
   230  	return i.hi == 0 && i.lo <= math.MaxInt64
   231  }
   232  
   233  // AsInt64 returns the Int128 as an int64.
   234  func (i Int128) AsInt64() int64 {
   235  	if i.hi&signBit != 0 {
   236  		return -int64(^(i.lo - 1))
   237  	}
   238  	return int64(i.lo)
   239  }
   240  
   241  // IsUint64 returns true if this value can be represented as a uint64 without any loss.
   242  func (i Int128) IsUint64() bool {
   243  	return i.hi == 0
   244  }
   245  
   246  // AsUint64 returns the Int128 as a uint64.
   247  func (i Int128) AsUint64() uint64 {
   248  	return i.lo
   249  }
   250  
   251  // Add returns i + n.
   252  func (i Int128) Add(n Int128) Int128 {
   253  	lo, carry := bits.Add64(i.lo, n.lo, 0)
   254  	hi, _ := bits.Add64(i.hi, n.hi, carry)
   255  	return Int128{
   256  		hi: hi,
   257  		lo: lo,
   258  	}
   259  }
   260  
   261  // Add64 returns i + n.
   262  func (i Int128) Add64(n int64) Int128 {
   263  	lo, carry := bits.Add64(i.lo, uint64(n), 0)
   264  	if n < 0 {
   265  		carry += math.MaxUint64
   266  	}
   267  	return Int128{
   268  		hi: i.hi + carry,
   269  		lo: lo,
   270  	}
   271  }
   272  
   273  // Sub returns i - n.
   274  func (i Int128) Sub(n Int128) Int128 {
   275  	lo, borrow := bits.Sub64(i.lo, n.lo, 0)
   276  	hi, _ := bits.Sub64(i.hi, n.hi, borrow)
   277  	return Int128{
   278  		hi: hi,
   279  		lo: lo,
   280  	}
   281  }
   282  
   283  // Sub64 returns i - n.
   284  func (i Int128) Sub64(n int64) Int128 {
   285  	lo, borrow := bits.Sub64(i.lo, uint64(n), 0)
   286  	hi := i.hi - borrow
   287  	if n < 0 {
   288  		hi -= math.MaxUint64
   289  	}
   290  	return Int128{
   291  		hi: hi,
   292  		lo: lo,
   293  	}
   294  }
   295  
   296  // Inc returns i + 1.
   297  func (i Int128) Inc() Int128 {
   298  	return Int128(Uint128(i).Inc())
   299  }
   300  
   301  // Dec returns i - 1.
   302  func (i Int128) Dec() Int128 {
   303  	return Int128(Uint128(i).Dec())
   304  }
   305  
   306  // Sign returns 1 if i > 0, 0 if i == 0, and -1 if i < 0.
   307  func (i Int128) Sign() int {
   308  	switch {
   309  	case i.hi|i.lo == 0:
   310  		return 0
   311  	case i.hi&signBit == 0:
   312  		return 1
   313  	default:
   314  		return -1
   315  	}
   316  }
   317  
   318  // Neg returns -i.
   319  func (i Int128) Neg() Int128 {
   320  	switch {
   321  	case i.hi|i.lo == 0 || i == MinInt128:
   322  		return i
   323  	case i.hi&signBit != 0:
   324  		hi := ^i.hi
   325  		lo := ^(i.lo - 1)
   326  		if lo == 0 {
   327  			hi++
   328  		}
   329  		return Int128{hi: hi, lo: lo}
   330  	default:
   331  		hi := ^i.hi
   332  		lo := (^i.lo) + 1
   333  		if lo == 0 {
   334  			hi++
   335  		}
   336  		return Int128{hi: hi, lo: lo}
   337  	}
   338  }
   339  
   340  // Abs returns the absolute value of i as an Int128.
   341  func (i Int128) Abs() Int128 {
   342  	if i.hi&signBit != 0 {
   343  		i.hi = ^i.hi
   344  		i.lo = ^(i.lo - 1)
   345  		if i.lo == 0 {
   346  			i.hi++
   347  		}
   348  	}
   349  	return i
   350  }
   351  
   352  // AbsUint128 returns the absolute value of i as a Uint128.
   353  func (i Int128) AbsUint128() Uint128 {
   354  	v := Uint128(i)
   355  	if i == MinInt128 {
   356  		return v
   357  	}
   358  	if i.hi&signBit != 0 {
   359  		v.hi = ^i.hi
   360  		v.lo = ^(i.lo - 1)
   361  		if v.lo == 0 {
   362  			v.hi++
   363  		}
   364  	}
   365  	return v
   366  }
   367  
   368  // Cmp returns 1 if i > n, 0 if i == n, and -1 if i < n.
   369  func (i Int128) Cmp(n Int128) int {
   370  	switch {
   371  	case i.hi == n.hi && i.lo == n.lo:
   372  		return 0
   373  	case i.hi&signBit == n.hi&signBit:
   374  		if i.hi > n.hi || (i.hi == n.hi && i.lo > n.lo) {
   375  			return 1
   376  		}
   377  	case i.hi&signBit == 0:
   378  		return 1
   379  	}
   380  	return -1
   381  }
   382  
   383  // Cmp64 returns 1 if i > n, 0 if i == n, and -1 if i < n.
   384  func (i Int128) Cmp64(n int64) int {
   385  	var nhi uint64
   386  	nlo := uint64(n)
   387  	if n < 0 {
   388  		nhi = math.MaxUint64
   389  	}
   390  	switch {
   391  	case i.hi == nhi && i.lo == nlo:
   392  		return 0
   393  	case i.hi&signBit == nhi&signBit:
   394  		if i.hi > nhi || (i.hi == nhi && i.lo > nlo) {
   395  			return 1
   396  		}
   397  	case i.hi&signBit == 0:
   398  		return 1
   399  	}
   400  	return -1
   401  }
   402  
   403  // GreaterThan returns true if i > n.
   404  func (i Int128) GreaterThan(n Int128) bool {
   405  	switch {
   406  	case i.hi&signBit == n.hi&signBit:
   407  		return i.hi > n.hi || (i.hi == n.hi && i.lo > n.lo)
   408  	case i.hi&signBit == 0:
   409  		return true
   410  	default:
   411  		return false
   412  	}
   413  }
   414  
   415  // GreaterThan64 returns true if i > n.
   416  func (i Int128) GreaterThan64(n int64) bool {
   417  	var nhi uint64
   418  	nlo := uint64(n)
   419  	if n < 0 {
   420  		nhi = math.MaxUint64
   421  	}
   422  	switch {
   423  	case i.hi&signBit == nhi&signBit:
   424  		return i.hi > nhi || (i.hi == nhi && i.lo > nlo)
   425  	case i.hi&signBit == 0:
   426  		return true
   427  	default:
   428  		return false
   429  	}
   430  }
   431  
   432  // GreaterThanOrEqual returns true if i >= n.
   433  func (i Int128) GreaterThanOrEqual(n Int128) bool {
   434  	switch {
   435  	case i.hi == n.hi && i.lo == n.lo:
   436  		return true
   437  	case i.hi&signBit == n.hi&signBit:
   438  		return i.hi > n.hi || (i.hi == n.hi && i.lo > n.lo)
   439  	case i.hi&signBit == 0:
   440  		return true
   441  	default:
   442  		return false
   443  	}
   444  }
   445  
   446  // GreaterThanOrEqual64 returns true if i >= n.
   447  func (i Int128) GreaterThanOrEqual64(n int64) bool {
   448  	var nhi uint64
   449  	nlo := uint64(n)
   450  	if n < 0 {
   451  		nhi = math.MaxUint64
   452  	}
   453  	switch {
   454  	case i.hi == nhi && i.lo == nlo:
   455  		return true
   456  	case i.hi&signBit == nhi&signBit:
   457  		return i.hi > nhi || (i.hi == nhi && i.lo > nlo)
   458  	case i.hi&signBit == 0:
   459  		return true
   460  	default:
   461  		return false
   462  	}
   463  }
   464  
   465  // Equal returns true if i == n.
   466  func (i Int128) Equal(n Int128) bool {
   467  	return i.hi == n.hi && i.lo == n.lo
   468  }
   469  
   470  // Equal64 returns true if i == n.
   471  func (i Int128) Equal64(n int64) bool {
   472  	var nhi uint64
   473  	nlo := uint64(n)
   474  	if n < 0 {
   475  		nhi = math.MaxUint64
   476  	}
   477  	return i.hi == nhi && i.lo == nlo
   478  }
   479  
   480  // LessThan returns true if i < n.
   481  func (i Int128) LessThan(n Int128) bool {
   482  	switch {
   483  	case i.hi&signBit == n.hi&signBit:
   484  		return i.hi < n.hi || (i.hi == n.hi && i.lo < n.lo)
   485  	case i.hi&signBit != 0:
   486  		return true
   487  	default:
   488  		return false
   489  	}
   490  }
   491  
   492  // LessThan64 returns true if i < n.
   493  func (i Int128) LessThan64(n int64) bool {
   494  	var nhi uint64
   495  	nlo := uint64(n)
   496  	if n < 0 {
   497  		nhi = math.MaxUint64
   498  	}
   499  	switch {
   500  	case i.hi&signBit == nhi&signBit:
   501  		return i.hi < nhi || (i.hi == nhi && i.lo < nlo)
   502  	case i.hi&signBit != 0:
   503  		return true
   504  	default:
   505  		return false
   506  	}
   507  }
   508  
   509  // LessThanOrEqual returns true if i <= n.
   510  func (i Int128) LessThanOrEqual(n Int128) bool {
   511  	switch {
   512  	case i.hi == n.hi && i.lo == n.lo:
   513  		return true
   514  	case i.hi&signBit == n.hi&signBit:
   515  		return i.hi < n.hi || (i.hi == n.hi && i.lo < n.lo)
   516  	case i.hi&signBit != 0:
   517  		return true
   518  	default:
   519  		return false
   520  	}
   521  }
   522  
   523  // LessThanOrEqual64 returns true if i <= n.
   524  func (i Int128) LessThanOrEqual64(n int64) bool {
   525  	var nhi uint64
   526  	nlo := uint64(n)
   527  	if n < 0 {
   528  		nhi = math.MaxUint64
   529  	}
   530  	switch {
   531  	case i.hi == nhi && i.lo == nlo:
   532  		return true
   533  	case i.hi&signBit == nhi&signBit:
   534  		return i.hi < nhi || (i.hi == nhi && i.lo < nlo)
   535  	case i.hi&signBit != 0:
   536  		return true
   537  	default:
   538  		return false
   539  	}
   540  }
   541  
   542  // Mul returns i * n.
   543  func (i Int128) Mul(n Int128) Int128 {
   544  	hi, lo := bits.Mul64(i.lo, n.lo)
   545  	return Int128{
   546  		hi: hi + i.hi*n.lo + i.lo*n.hi,
   547  		lo: lo,
   548  	}
   549  }
   550  
   551  // Mul64 returns i * n.
   552  func (i Int128) Mul64(n int64) Int128 {
   553  	return i.Mul(Int128From64(n))
   554  }
   555  
   556  // Div returns i / n. If n == 0, a divide by zero panic will occur.
   557  func (i Int128) Div(n Int128) Int128 {
   558  	qSign := 1
   559  	if i.LessThan(Int128{}) {
   560  		qSign = -1
   561  		//goland:noinspection GoAssignmentToReceiver
   562  		i = i.Neg()
   563  	}
   564  	if n.LessThan(Int128{}) {
   565  		qSign = -qSign
   566  		n = n.Neg()
   567  	}
   568  	q := Int128(Uint128(i).Div(Uint128(n)))
   569  	if qSign < 0 {
   570  		q = q.Neg()
   571  	}
   572  	return q
   573  }
   574  
   575  // Div64 returns i / n. If n == 0, a divide by zero panic will occur.
   576  func (i Int128) Div64(n int64) Int128 {
   577  	qSign := 1
   578  	if i.LessThan(Int128{}) {
   579  		qSign = -1
   580  		//goland:noinspection GoAssignmentToReceiver
   581  		i = i.Neg()
   582  	}
   583  	if n < 0 {
   584  		qSign = -qSign
   585  		n = -n
   586  	}
   587  	q := Int128(Uint128(i).Div64(uint64(n)))
   588  	if qSign < 0 {
   589  		q = q.Neg()
   590  	}
   591  	return q
   592  }
   593  
   594  // DivMod returns both the result of i / n as well i % n. If n == 0, a divide by zero panic will occur.
   595  func (i Int128) DivMod(n Int128) (q, r Int128) {
   596  	qSign := 1
   597  	rSign := 1
   598  	if i.LessThan(Int128{}) {
   599  		qSign = -1
   600  		rSign = -1
   601  		//goland:noinspection GoAssignmentToReceiver
   602  		i = i.Neg()
   603  	}
   604  	if n.LessThan(Int128{}) {
   605  		qSign = -qSign
   606  		n = n.Neg()
   607  	}
   608  	qu, ru := Uint128(i).DivMod(Uint128(n))
   609  	q = Int128(qu)
   610  	r = Int128(ru)
   611  	if qSign < 0 {
   612  		q = q.Neg()
   613  	}
   614  	if rSign < 0 {
   615  		r = r.Neg()
   616  	}
   617  	return q, r
   618  }
   619  
   620  // DivMod64 returns both the result of i / n as well i % n. If n == 0, a divide by zero panic will occur.
   621  func (i Int128) DivMod64(n int64) (q, r Int128) {
   622  	var hi uint64
   623  	if n < 0 {
   624  		hi = math.MaxUint64
   625  	}
   626  	return i.DivMod(Int128{hi: hi, lo: uint64(n)})
   627  }
   628  
   629  // Mod returns i % n. If n == 0, a divide by zero panic will occur.
   630  func (i Int128) Mod(n Int128) (r Int128) {
   631  	_, r = i.DivMod(n)
   632  	return r
   633  }
   634  
   635  // Mod64 returns i % n. If n == 0, a divide by zero panic will occur.
   636  func (i Int128) Mod64(n int64) (r Int128) {
   637  	_, r = i.DivMod64(n)
   638  	return r
   639  }
   640  
   641  // String implements fmt.Stringer.
   642  func (i Int128) String() string {
   643  	if i.hi == 0 {
   644  		if i.lo == 0 {
   645  			return "0"
   646  		}
   647  		return strconv.FormatUint(i.lo, 10)
   648  	}
   649  	return i.AsBigInt().String()
   650  }
   651  
   652  // Format implements fmt.Formatter.
   653  func (i Int128) Format(s fmt.State, c rune) {
   654  	i.AsBigInt().Format(s, c)
   655  }
   656  
   657  // Scan implements fmt.Scanner.
   658  func (i *Int128) Scan(state fmt.ScanState, _ rune) error {
   659  	t, err := state.Token(true, nil)
   660  	if err != nil {
   661  		return errs.Wrap(err)
   662  	}
   663  	var v Int128
   664  	if v, err = Int128FromString(string(t)); err != nil {
   665  		return errs.Wrap(err)
   666  	}
   667  	*i = v
   668  	return nil
   669  }
   670  
   671  // MarshalText implements encoding.TextMarshaler.
   672  func (i Int128) MarshalText() ([]byte, error) {
   673  	return []byte(i.String()), nil
   674  }
   675  
   676  // UnmarshalText implements encoding.TextUnmarshaler.
   677  func (i *Int128) UnmarshalText(text []byte) error {
   678  	v, err := Int128FromString(string(text))
   679  	if err != nil {
   680  		return err
   681  	}
   682  	*i = v
   683  	return nil
   684  }
   685  
   686  // Float64 implements json.Number. Intentionally always returns an error, as we never want to emit floating point values
   687  // into json for Int128.
   688  func (i Int128) Float64() (float64, error) {
   689  	return 0, errNoFloat64
   690  }
   691  
   692  // Int64 implements json.Number.
   693  func (i Int128) Int64() (int64, error) {
   694  	if !i.IsInt64() {
   695  		return 0, errDoesNotFitInInt64
   696  	}
   697  	return i.AsInt64(), nil
   698  }
   699  
   700  // MarshalJSON implements json.Marshaler.
   701  func (i Int128) MarshalJSON() ([]byte, error) {
   702  	return []byte(i.String()), nil
   703  }
   704  
   705  // UnmarshalJSON implements json.Unmarshaler.
   706  func (i *Int128) UnmarshalJSON(in []byte) error {
   707  	v, err := Int128FromString(string(in))
   708  	if err != nil {
   709  		return err
   710  	}
   711  	*i = v
   712  	return nil
   713  }
   714  
   715  // MarshalYAML implements yaml.Marshaler.
   716  func (i Int128) MarshalYAML() (any, error) {
   717  	return i.String(), nil
   718  }
   719  
   720  // UnmarshalYAML implements yaml.Unmarshaler.
   721  func (i *Int128) UnmarshalYAML(unmarshal func(any) error) error {
   722  	var str string
   723  	if err := unmarshal(&str); err != nil {
   724  		return err
   725  	}
   726  	v, err := Int128FromString(str)
   727  	if err != nil {
   728  		return err
   729  	}
   730  	*i = v
   731  	return nil
   732  }