github.com/ericlagergren/ctb@v0.0.0-20220810041818-96749d9c394d/xbits/ct/ct.go (about)

     1  package ct
     2  
     3  import "fmt"
     4  
     5  // LessOrEq returns 1 if x <= y and 0 otherwise.
     6  //
     7  // See golang.org/issues/42685.
     8  func LessOrEq(x, y uint) uint {
     9  	x64 := uint64(x)
    10  	y64 := uint64(y)
    11  
    12  	gtb := x64 & ^y64
    13  	ltb := ^x64 & y64
    14  
    15  	ltb |= (ltb >> 1)
    16  	ltb |= (ltb >> 2)
    17  	ltb |= (ltb >> 4)
    18  	ltb |= (ltb >> 8)
    19  	ltb |= (ltb >> 16)
    20  	ltb |= (ltb >> 32)
    21  
    22  	bit := gtb &^ ltb
    23  
    24  	bit |= (bit >> 1)
    25  	bit |= (bit >> 2)
    26  	bit |= (bit >> 4)
    27  	bit |= (bit >> 8)
    28  	bit |= (bit >> 16)
    29  	bit |= (bit >> 32)
    30  
    31  	return uint(^bit & 1)
    32  }
    33  
    34  // Greater returns 1 if x > y and 0 otherwise.
    35  //
    36  // See golang.org/issues/42685.
    37  func Greater(x, y uint64) uint64 {
    38  	gtb := x & ^y
    39  	ltb := ^x & y
    40  
    41  	ltb |= (ltb >> 1)
    42  	ltb |= (ltb >> 2)
    43  	ltb |= (ltb >> 4)
    44  	ltb |= (ltb >> 8)
    45  	ltb |= (ltb >> 16)
    46  	ltb |= (ltb >> 32)
    47  
    48  	bit := gtb &^ ltb
    49  
    50  	bit |= (bit >> 1)
    51  	bit |= (bit >> 2)
    52  	bit |= (bit >> 4)
    53  	bit |= (bit >> 8)
    54  	bit |= (bit >> 16)
    55  	bit |= (bit >> 32)
    56  
    57  	return bit & 1
    58  }
    59  
    60  // greater32 returns 1 if x > y and 0 otherwise.
    61  //
    62  // See golang.org/issues/42685.
    63  func greater32(x, y uint32) uint32 {
    64  	gtb := x & ^y
    65  	ltb := ^x & y
    66  
    67  	ltb |= (ltb >> 1)
    68  	ltb |= (ltb >> 2)
    69  	ltb |= (ltb >> 4)
    70  	ltb |= (ltb >> 8)
    71  	ltb |= (ltb >> 16)
    72  
    73  	bit := gtb &^ ltb
    74  
    75  	bit |= (bit >> 1)
    76  	bit |= (bit >> 2)
    77  	bit |= (bit >> 4)
    78  	bit |= (bit >> 8)
    79  	bit |= (bit >> 16)
    80  
    81  	return bit & 1
    82  }
    83  
    84  func GreaterEq32(x, y uint32) uint32 {
    85  	return greater32(y, x) ^ 1
    86  }
    87  
    88  func GreaterEq64(x, y uint64) uint64 {
    89  	return Greater(y, x) ^ 1
    90  }
    91  
    92  // Equal64 returns 1 if x == y and 0 otherwise.
    93  func Equal32(x, y uint32) uint32 {
    94  	return uint32((uint64(x^y) - 1) >> 63)
    95  }
    96  
    97  // Equal64 returns 1 if x == y and 0 otherwise.
    98  func Equal64(x, y uint64) uint64 {
    99  	return (uint64(x^y) - 1) >> 63
   100  }
   101  
   102  // Select returns x if v == 1 and y if v == 0.
   103  //
   104  // The result is undefined if v is anything
   105  // other than 1 or 0.
   106  func Select32(v, x, y uint32) uint32 {
   107  	return ^(v-1)&x | (v-1)&y
   108  }
   109  
   110  // Select returns x if v == 1 and y if v == 0.
   111  //
   112  // The result is undefined if v is anything
   113  // other than 1 or 0.
   114  func Select64(v, x, y uint64) uint64 {
   115  	return ^(v-1)&x | (v-1)&y
   116  }
   117  
   118  // Div64 returns q = (hi, lo) / d and r = (hi, lo) % d.
   119  func Div32(hi, lo, d uint32) (q, r uint32) {
   120  	ch := Equal32(hi, d)
   121  	hi = Select32(ch, 0, hi)
   122  	for k := 31; k > 0; k-- {
   123  		j := 32 - k
   124  		w := (hi << j) | (lo >> k)
   125  		ctl := GreaterEq32(w, d) | (hi >> k)
   126  		hi2 := (w - d) >> j
   127  		lo2 := lo - (d << k)
   128  		hi = Select32(ctl, hi2, hi)
   129  		lo = Select32(ctl, lo2, lo)
   130  		q |= ctl << k
   131  	}
   132  	cf := GreaterEq32(lo, d) | hi
   133  	q |= cf
   134  	r = Select32(cf, lo-d, lo)
   135  	return q, r
   136  }
   137  
   138  // Div64 returns q = (hi, lo) / d and r = (hi, lo) % d.
   139  func Div64(hi, lo, d uint64) (q, r uint64) {
   140  	ch := Equal64(hi, d)
   141  	hi = Select64(ch, 0, hi)
   142  	for k := 63; k > 0; k-- {
   143  		j := 64 - k
   144  		w := (hi << j) | (lo >> k)
   145  		ctl := GreaterEq64(w, d) | (hi >> k)
   146  		hi2 := (w - d) >> j
   147  		lo2 := lo - (d << k)
   148  		fmt.Printf("lo=%d lo2=%d d=%d k=%d\n", lo, lo2, d, k)
   149  		hi = Select64(ctl, hi2, hi)
   150  		lo = Select64(ctl, lo2, lo)
   151  		q |= ctl << k
   152  	}
   153  	cf := GreaterEq64(lo, d) | hi
   154  	q |= cf
   155  	r = Select64(cf, lo-d, lo)
   156  	return q, r
   157  }