github.com/Aoi-hosizora/ahlib@v1.5.1-0.20230404072829-241b93cf91c7/xnumber/xnumber_range.go (about) 1 package xnumber 2 3 import ( 4 "math" 5 ) 6 7 // checkSignedRange checks whether given signed integer from, to and step arguments is legal to represent a range, and also calculates the range slice capacity. 8 func checkSignedRange(from, to, step int64) (capacity int, legal bool) { 9 if step > 0 && from < to { 10 return int(math.Ceil(float64(to-from) / float64(step))), true 11 } 12 if step < 0 && from > to { 13 return int(math.Ceil(float64(from-to) / float64(-step))), true 14 } 15 return 0, false 16 } 17 18 // checkUnsignedRange checks whether given unsigned integer from, to and step arguments is legal to represent a range, and also calculates the range slice capacity. 19 func checkUnsignedRange(from, to, step uint64, reverse bool) (capacity int, legal bool) { 20 if step != 0 && !reverse /* step > 0 */ && from < to { 21 return int(math.Ceil(float64(to-from) / float64(step))), true 22 } 23 if step != 0 && reverse /* step < 0 */ && from > to { 24 return int(math.Ceil(float64(from-to) / float64(-step))), true 25 } 26 return 0, false 27 } 28 29 // ============== 30 // signed integer 31 // ============== 32 33 // IntRange returns an int slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by using a negative step. 34 func IntRange(from, to, step int) []int { 35 capacity, ok := checkSignedRange(int64(from), int64(to), int64(step)) 36 if !ok { 37 return nil 38 } 39 out := make([]int, 0, capacity) 40 if step > 0 { 41 for i := from; i < to; i += step { 42 out = append(out, i) 43 if OverflowWhenAddInt(i, step) { 44 break 45 } 46 } 47 } else { 48 for i := from; i > to; i += step { 49 out = append(out, i) 50 if OverflowWhenAddInt(i, step) { 51 break 52 } 53 } 54 } 55 return out 56 } 57 58 // Int8Range returns an int8 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by using a negative step. 59 func Int8Range(from, to, step int8) []int8 { 60 capacity, ok := checkSignedRange(int64(from), int64(to), int64(step)) 61 if !ok { 62 return nil 63 } 64 out := make([]int8, 0, capacity) 65 if step > 0 { 66 for i := from; i < to; i += step { 67 out = append(out, i) 68 if OverflowWhenAddInt8(i, step) { 69 break 70 } 71 } 72 } else { 73 for i := from; i > to; i += step { 74 out = append(out, i) 75 if OverflowWhenAddInt8(i, step) { 76 break 77 } 78 } 79 } 80 return out 81 } 82 83 // Int16Range returns an int16 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by using a negative step. 84 func Int16Range(from, to, step int16) []int16 { 85 capacity, ok := checkSignedRange(int64(from), int64(to), int64(step)) 86 if !ok { 87 return nil 88 } 89 out := make([]int16, 0, capacity) 90 if step > 0 { 91 for i := from; i < to; i += step { 92 out = append(out, i) 93 if OverflowWhenAddInt16(i, step) { 94 break 95 } 96 } 97 } else { 98 for i := from; i > to; i += step { 99 out = append(out, i) 100 if OverflowWhenAddInt16(i, step) { 101 break 102 } 103 } 104 } 105 return out 106 } 107 108 // Int32Range returns an int32 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by using a negative step. 109 func Int32Range(from, to, step int32) []int32 { 110 capacity, ok := checkSignedRange(int64(from), int64(to), int64(step)) 111 if !ok { 112 return nil 113 } 114 out := make([]int32, 0, capacity) 115 if step > 0 { 116 for i := from; i < to; i += step { 117 out = append(out, i) 118 if OverflowWhenAddInt32(i, step) { 119 break 120 } 121 } 122 } else { 123 for i := from; i > to; i += step { 124 out = append(out, i) 125 if OverflowWhenAddInt32(i, step) { 126 break 127 } 128 } 129 } 130 return out 131 } 132 133 // Int64Range returns an int64 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by using a negative step. 134 func Int64Range(from, to, step int64) []int64 { 135 capacity, ok := checkSignedRange(from, to, step) 136 if !ok { 137 return nil 138 } 139 out := make([]int64, 0, capacity) 140 if step > 0 { 141 for i := from; i < to; i += step { 142 out = append(out, i) 143 if OverflowWhenAddInt64(i, step) { 144 break 145 } 146 } 147 } else { 148 for i := from; i > to; i += step { 149 out = append(out, i) 150 if OverflowWhenAddInt64(i, step) { 151 break 152 } 153 } 154 } 155 return out 156 } 157 158 // ================ 159 // unsigned integer 160 // ================ 161 162 // UintRange returns an uint slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by set the first value of reverseFlag to true. 163 func UintRange(from, to, step uint, reverseFlag ...bool) []uint { 164 reservedStep := len(reverseFlag) >= 1 && reverseFlag[0] 165 capacity, ok := checkUnsignedRange(uint64(from), uint64(to), uint64(step), reservedStep) 166 if !ok { 167 return nil 168 } 169 out := make([]uint, 0, capacity) 170 if !reservedStep { 171 for i := from; i < to; i += step { 172 out = append(out, i) 173 if OverflowWhenAddUint(i, step) { 174 break 175 } 176 } 177 } else { 178 for i := from; i > to; i -= step { 179 out = append(out, i) 180 if OverflowWhenSubtractUint(i, step) { 181 break 182 } 183 } 184 } 185 return out 186 } 187 188 // Uint8Range returns an uint8 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by set the first value of reverseFlag to true. 189 func Uint8Range(from, to, step uint8, reverseFlag ...bool) []uint8 { 190 reservedStep := len(reverseFlag) >= 1 && reverseFlag[0] 191 capacity, ok := checkUnsignedRange(uint64(from), uint64(to), uint64(step), reservedStep) 192 if !ok { 193 return nil 194 } 195 out := make([]uint8, 0, capacity) 196 if !reservedStep { 197 for i := from; i < to; i += step { 198 out = append(out, i) 199 if OverflowWhenAddUint8(i, step) { 200 break 201 } 202 } 203 } else { 204 for i := from; i > to; i -= step { 205 out = append(out, i) 206 if OverflowWhenSubtractUint8(i, step) { 207 break 208 } 209 } 210 } 211 return out 212 } 213 214 // Uint16Range returns an uint16 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by set the first value of reverseFlag to true. 215 func Uint16Range(from, to, step uint16, reverseFlag ...bool) []uint16 { 216 reservedStep := len(reverseFlag) >= 1 && reverseFlag[0] 217 capacity, ok := checkUnsignedRange(uint64(from), uint64(to), uint64(step), reservedStep) 218 if !ok { 219 return nil 220 } 221 out := make([]uint16, 0, capacity) 222 if !reservedStep { 223 for i := from; i < to; i += step { 224 out = append(out, i) 225 if OverflowWhenAddUint16(i, step) { 226 break 227 } 228 } 229 } else { 230 for i := from; i > to; i -= step { 231 out = append(out, i) 232 if OverflowWhenSubtractUint16(i, step) { 233 break 234 } 235 } 236 } 237 return out 238 } 239 240 // Uint32Range returns an uint32 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by set the first value of reverseFlag to true. 241 func Uint32Range(from, to, step uint32, reverseFlag ...bool) []uint32 { 242 reservedStep := len(reverseFlag) >= 1 && reverseFlag[0] 243 capacity, ok := checkUnsignedRange(uint64(from), uint64(to), uint64(step), reservedStep) 244 if !ok { 245 return nil 246 } 247 out := make([]uint32, 0, capacity) 248 if !reservedStep { 249 for i := from; i < to; i += step { 250 out = append(out, i) 251 if OverflowWhenAddUint32(i, step) { 252 break 253 } 254 } 255 } else { 256 for i := from; i > to; i -= step { 257 out = append(out, i) 258 if OverflowWhenSubtractUint32(i, step) { 259 break 260 } 261 } 262 } 263 return out 264 } 265 266 // Uint64Range returns an uint64 slice as range [from, to) with step. Note that a reversed range (to, from] can be generated by set the first value of reverseFlag to true. 267 func Uint64Range(from, to, step uint64, reverseFlag ...bool) []uint64 { 268 reservedStep := len(reverseFlag) >= 1 && reverseFlag[0] 269 capacity, ok := checkUnsignedRange(from, to, step, reservedStep) 270 if !ok { 271 return nil 272 } 273 out := make([]uint64, 0, capacity) 274 if !reservedStep { 275 for i := from; i < to; i += step { 276 out = append(out, i) 277 if OverflowWhenAddUint64(i, step) { 278 break 279 } 280 } 281 } else { 282 for i := from; i > to; i -= step { 283 out = append(out, i) 284 if OverflowWhenSubtractUint64(i, step) { 285 break 286 } 287 } 288 } 289 return out 290 } 291 292 // ============= 293 // reverse slice 294 // ============= 295 296 // ReverseIntSlice reverses given int slice directly. 297 func ReverseIntSlice(s []int) { 298 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 299 s[i], s[j] = s[j], s[i] 300 } 301 } 302 303 // ReverseInt8Slice reverses given int8 slice directly. 304 func ReverseInt8Slice(s []int8) { 305 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 306 s[i], s[j] = s[j], s[i] 307 } 308 } 309 310 // ReverseInt16Slice reverses given int16 slice directly. 311 func ReverseInt16Slice(s []int16) { 312 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 313 s[i], s[j] = s[j], s[i] 314 } 315 } 316 317 // ReverseInt32Slice reverses given int32 slice directly. 318 func ReverseInt32Slice(s []int32) { 319 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 320 s[i], s[j] = s[j], s[i] 321 } 322 } 323 324 // ReverseInt64Slice reverses given int64 slice directly. 325 func ReverseInt64Slice(s []int64) { 326 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 327 s[i], s[j] = s[j], s[i] 328 } 329 } 330 331 // ReverseUintSlice reverses given uint slice directly. 332 func ReverseUintSlice(s []uint) { 333 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 334 s[i], s[j] = s[j], s[i] 335 } 336 } 337 338 // ReverseUint8Slice reverses given uint8 slice directly. 339 func ReverseUint8Slice(s []uint8) { 340 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 341 s[i], s[j] = s[j], s[i] 342 } 343 } 344 345 // ReverseUint16Slice reverses given uint16 slice directly. 346 func ReverseUint16Slice(s []uint16) { 347 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 348 s[i], s[j] = s[j], s[i] 349 } 350 } 351 352 // ReverseUint32Slice reverses given uint32 slice directly. 353 func ReverseUint32Slice(s []uint32) { 354 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 355 s[i], s[j] = s[j], s[i] 356 } 357 } 358 359 // ReverseUint64Slice reverses given uint64 slice directly. 360 func ReverseUint64Slice(s []uint64) { 361 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 362 s[i], s[j] = s[j], s[i] 363 } 364 }