| 1 | import math.big |
| 2 | import math.unsigned |
| 3 | import rand |
| 4 | |
| 5 | fn test_str() { |
| 6 | x := unsigned.uint128_from_dec_str('170141183460469231713240559642174554112') or { panic('') } |
| 7 | assert x.str() == '170141183460469231713240559642174554112' |
| 8 | y := unsigned.uint128_from_64(42) |
| 9 | assert y.str() == '42' |
| 10 | } |
| 11 | |
| 12 | fn test_ops() { |
| 13 | x := unsigned.uint128_from_64(18446744073709551615) |
| 14 | y := unsigned.uint128_from_64(18446744073709551615) |
| 15 | z := unsigned.uint128_from_dec_str('340282366920938463426481119284349108225') or { |
| 16 | assert false |
| 17 | panic('') |
| 18 | } |
| 19 | assert (x * y).str() == '340282366920938463426481119284349108225' |
| 20 | assert (x + y).str() == '36893488147419103230' |
| 21 | assert (z / unsigned.uint128_from_64(2)).str() == '170141183460469231713240559642174554112' |
| 22 | assert (unsigned.uint128_from_dec_str('170141183460469231713240559642174554112') or { |
| 23 | panic('') |
| 24 | } - unsigned.uint128_from_64(2)).str() == '170141183460469231713240559642174554110' |
| 25 | |
| 26 | assert x == y |
| 27 | assert unsigned.uint128_from_dec_str('340282366920938463426481119284349108225') or { |
| 28 | assert false |
| 29 | panic('') |
| 30 | } > y |
| 31 | } |
| 32 | |
| 33 | struct LeadingZeros { |
| 34 | l unsigned.Uint128 |
| 35 | r unsigned.Uint128 |
| 36 | zeros int |
| 37 | } |
| 38 | |
| 39 | fn new(x u64, y u64) unsigned.Uint128 { |
| 40 | return unsigned.Uint128{x, y} |
| 41 | } |
| 42 | |
| 43 | fn test_leading_zeros() { |
| 44 | tcs := [ |
| 45 | LeadingZeros{ |
| 46 | l: new(0x00, 0xf000000000000000) |
| 47 | r: new(0x00, 0x8000000000000000) |
| 48 | zeros: 1 |
| 49 | }, |
| 50 | LeadingZeros{ |
| 51 | l: new(0x00, 0xf000000000000000) |
| 52 | r: new(0x00, 0xc000000000000000) |
| 53 | zeros: 2 |
| 54 | }, |
| 55 | LeadingZeros{ |
| 56 | l: new(0x00, 0xf000000000000000) |
| 57 | r: new(0x00, 0xe000000000000000) |
| 58 | zeros: 3 |
| 59 | }, |
| 60 | LeadingZeros{ |
| 61 | l: new(0x00, 0xffff000000000000) |
| 62 | r: new(0x00, 0xff00000000000000) |
| 63 | zeros: 8 |
| 64 | }, |
| 65 | LeadingZeros{ |
| 66 | l: new(0x00, 0x000000000000ffff) |
| 67 | r: new(0x00, 0x000000000000ff00) |
| 68 | zeros: 56 |
| 69 | }, |
| 70 | LeadingZeros{ |
| 71 | l: new(0xf000000000000000, 0x01) |
| 72 | r: new(0x4000000000000000, 0x00) |
| 73 | zeros: 63 |
| 74 | }, |
| 75 | LeadingZeros{ |
| 76 | l: new(0xf000000000000000, 0x00) |
| 77 | r: new(0x4000000000000000, 0x00) |
| 78 | zeros: 64 |
| 79 | }, |
| 80 | LeadingZeros{ |
| 81 | l: new(0xf000000000000000, 0x00) |
| 82 | r: new(0x8000000000000000, 0x00) |
| 83 | zeros: 65 |
| 84 | }, |
| 85 | LeadingZeros{ |
| 86 | l: new(0x00, 0x00) |
| 87 | r: new(0x00, 0x00) |
| 88 | zeros: 128 |
| 89 | }, |
| 90 | LeadingZeros{ |
| 91 | l: new(0x01, 0x00) |
| 92 | r: new(0x00, 0x00) |
| 93 | zeros: 127 |
| 94 | }, |
| 95 | ] |
| 96 | |
| 97 | for tc in tcs { |
| 98 | zeros := tc.l.xor(tc.r).leading_zeros() |
| 99 | assert zeros == tc.zeros |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | fn test_separators() { |
| 104 | // numbers of varying lengths and a random |
| 105 | // scattering of '_' throughout. |
| 106 | test_strings := [ |
| 107 | '_', |
| 108 | '__', |
| 109 | '_0', |
| 110 | '0_', |
| 111 | '_0_', |
| 112 | '_1', |
| 113 | '1_', |
| 114 | '_1_', |
| 115 | '1_2', |
| 116 | '_12', |
| 117 | '12_', |
| 118 | '12_3', |
| 119 | '1_23_4', |
| 120 | '12_345', |
| 121 | '_123_456_', |
| 122 | '1_234_567', |
| 123 | '1234_5678', |
| 124 | '_123456789', |
| 125 | '1234567890_', |
| 126 | '0_123_456_789_0', |
| 127 | '90_12_345_67890', |
| 128 | '8901_234_567890_', |
| 129 | '_7890_123456789_0', |
| 130 | '678901234_567890', |
| 131 | '567890_1234567890', |
| 132 | '4567890123__4567890', |
| 133 | '_34567890123_4567890', |
| 134 | '2345678_90123_4567890', |
| 135 | '123456789_01_234567890', |
| 136 | '01234567_8901234567890', |
| 137 | '9012345678901_234567890__', |
| 138 | '8_90123456_78901234567890', |
| 139 | '78901234567890_123_4567890', |
| 140 | '___67890123_4_5_6_78901234567890___', |
| 141 | '567890123_45678901234567890', |
| 142 | '45_67890123456789_01234567890', |
| 143 | '3456789012_345678901234567890', |
| 144 | '234_567890_1234_5__67890_1234567890_', |
| 145 | '12345678_90123_456789_0123_4567890', |
| 146 | '0_123_456_789_012_345_678_901_234_567_890', |
| 147 | '90_123456__78901__234567_8901_234567890', |
| 148 | '890123456789012345678901234567_890', |
| 149 | '7890_1234567_8901234567890_1234567890', |
| 150 | '67890123_45678_901234567_8901234567890', |
| 151 | '567890_1234567890_12345678901_234567890', |
| 152 | '45678_9012345_6789012345678901234567890_', |
| 153 | '34567890123456_789012345678901234567890', |
| 154 | '234567_890_1234567890_1234567890_1234567890', |
| 155 | '334567890_1234567890_1234567890_1234567890', |
| 156 | '340282360_0000000000_0000000000_0000000000', |
| 157 | '340282366_9209384634_2648111928_4349108225', |
| 158 | '340282366_9209384634_6337460743_1768211455', |
| 159 | ] |
| 160 | |
| 161 | for ts in test_strings { |
| 162 | with := unsigned.uint128_from_dec_str(ts) or { |
| 163 | assert false, 'invalid Uint128 string ${ts}' |
| 164 | panic('') |
| 165 | } |
| 166 | |
| 167 | without := unsigned.uint128_from_dec_str(ts.replace('_', '')) or { |
| 168 | assert false, 'invalid Uint128 string ${ts.replace('_', '')}' |
| 169 | panic('') |
| 170 | } |
| 171 | |
| 172 | assert with == without |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | fn test_new() { |
| 177 | assert unsigned.uint128_new(max_u64, max_u64) == unsigned.uint128_max |
| 178 | } |
| 179 | |
| 180 | fn test_lsh() { |
| 181 | a := unsigned.uint128_from_dec_str('123456789012345678901234567890')! |
| 182 | assert a.str() == a.lsh(0).str() |
| 183 | assert '246913578024691357802469135780' == a.lsh(1).str() |
| 184 | assert '259801135457060040952792416454273138688' == a.lsh(64).str() |
| 185 | assert '302984417681386893975453667670529933312' == a.lsh(100).str() |
| 186 | assert unsigned.uint128_zero == a.lsh(200) |
| 187 | } |
| 188 | |
| 189 | fn test_rsh() { |
| 190 | a := unsigned.uint128_from_dec_str('279625844435276397900870454226348864638')! |
| 191 | assert a.str() == a.rsh(0).str() |
| 192 | assert '139812922217638198950435227113174432319' == a.rsh(1).str() |
| 193 | assert '15158547400991018568' == a.rsh(64).str() |
| 194 | assert '220585896' == a.rsh(100).str() |
| 195 | assert '1' == a.rsh(127).str() |
| 196 | assert unsigned.uint128_zero == a.rsh(200) |
| 197 | } |
| 198 | |
| 199 | fn test_quo_rem() { |
| 200 | for a_lo in 0 .. 16 { |
| 201 | for a_hi in 0 .. 16 { |
| 202 | for b_lo in 0 .. 16 { |
| 203 | for b_hi in 0 .. 16 { |
| 204 | a := unsigned.uint128_new(u64(1 << a_lo), u64(1 << a_hi)) |
| 205 | b := unsigned.uint128_new(u64(1 << b_lo), u64(1 << b_hi)) |
| 206 | big_a := big.integer_from_string(a.str())! |
| 207 | big_b := big.integer_from_string(b.str())! |
| 208 | q, r := a.quo_rem(b) |
| 209 | big_q, big_r := big_a.div_mod(big_b) |
| 210 | assert q.str() == big_q.str() |
| 211 | assert r.str() == big_r.str() |
| 212 | } |
| 213 | } |
| 214 | } |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | fn test_div_128() { |
| 219 | for a_lo in 0 .. 4 { |
| 220 | for a_hi in 0 .. 4 { |
| 221 | for b_lo in 0 .. 4 { |
| 222 | for b_hi in 0 .. 4 { |
| 223 | for c_lo in 0 .. 4 { |
| 224 | for c_hi in 0 .. 4 { |
| 225 | a := unsigned.uint128_new(u64(1 << a_lo), u64(1 << a_hi)) |
| 226 | b := unsigned.uint128_new(u64(1 << b_lo), u64(1 << b_hi)) |
| 227 | c := unsigned.uint128_new(u64(1 << c_lo), u64(1 << c_hi)) |
| 228 | if c.cmp(a) <= 0 { |
| 229 | continue |
| 230 | } |
| 231 | aa := unsigned.uint256_new(b, a) |
| 232 | big_a := big.integer_from_string(aa.str())! |
| 233 | big_b := big.integer_from_string(c.str())! |
| 234 | q, r := unsigned.div_128(a, b, c) |
| 235 | big_q, big_r := big_a.div_mod(big_b) |
| 236 | assert q.str() == big_q.str() |
| 237 | assert r.str() == big_r.str() |
| 238 | } |
| 239 | } |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | fn test_put_bytes() { |
| 247 | a := unsigned.uint128_new(rand.u64(), rand.u64()) |
| 248 | b := a.reverse_bytes() |
| 249 | mut buf_a := []u8{len: 16} |
| 250 | mut buf_b := []u8{len: 16} |
| 251 | a.put_bytes(mut buf_a) |
| 252 | b.put_bytes(mut buf_b) |
| 253 | assert buf_a == buf_b.reverse() |
| 254 | } |
| 255 | |