Add SIMD random that supports supports different ranges on each SIMD index

Introduction

The SIMD type currently support a .random static method that takes a Rang of the same type as the underlying scalar that is packed within the SIMD vector.

However I would like to propose that we add an additional random method that can be used to generate a random number within a different range for each index of the SIMD.

The problem

When writing numerical optimisers (Particle Swarm, Ant Colony etc) it is very useful (and faster) to represent positions in the search space using a SIMD vector.

Within the nested loops of these methods we are required to regularly create new random vectors in this search space however in many cases the the optimisation problem you are solving the range of values for each dimension of the search space is different.

How might this look

  @inlinable
  public static func random<T: RandomNumberGenerator>(
    lower: Self,
    upper: Self,
    using generator: inout T
  ) -> Self {
    var result = Self()
    for i in result.indices {
      result[i] = Scalar.random(in: lower[i]..<upper[i], using: &generator)
    }
    return result
  }

We would also want to include a closed range version of this. And include the simpler versions were you do not need to pass the generator.