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  }