mirror of
				https://github.com/ml-explore/mlx.git
				synced 2025-11-04 18:48:15 +08:00 
			
		
		
		
	Add loc and scale to random.normal (#638)
* Add loc and scale to random.normal * Add tests for loc and scale for random.normal * Run pre-commit hooks * Fix code review
This commit is contained in:
		@@ -153,14 +153,23 @@ array uniform(
 | 
				
			|||||||
array normal(
 | 
					array normal(
 | 
				
			||||||
    const std::vector<int>& shape,
 | 
					    const std::vector<int>& shape,
 | 
				
			||||||
    Dtype dtype,
 | 
					    Dtype dtype,
 | 
				
			||||||
 | 
					    const float loc /* = 0.0 */,
 | 
				
			||||||
 | 
					    const float scale /* = 1.0 */,
 | 
				
			||||||
    const std::optional<array>& key /*= nullopt */,
 | 
					    const std::optional<array>& key /*= nullopt */,
 | 
				
			||||||
    StreamOrDevice s /* = {} */) {
 | 
					    StreamOrDevice s /* = {} */) {
 | 
				
			||||||
  auto stream = to_stream(s);
 | 
					  auto stream = to_stream(s);
 | 
				
			||||||
  auto low = array(std::nextafter(-1.0f, 0.0f), dtype);
 | 
					  auto low = array(std::nextafter(-1.0f, 0.0f), dtype);
 | 
				
			||||||
  auto high = array(1.0f, dtype);
 | 
					  auto high = array(1.0f, dtype);
 | 
				
			||||||
  auto samples = uniform(low, high, shape, dtype, key, stream);
 | 
					  auto samples = uniform(low, high, shape, dtype, key, stream);
 | 
				
			||||||
  return multiply(
 | 
					  samples =
 | 
				
			||||||
      array(std::sqrt(2.0), dtype), erfinv(samples, stream), stream);
 | 
					      multiply(array(std::sqrt(2.0), dtype), erfinv(samples, stream), stream);
 | 
				
			||||||
 | 
					  if (scale != 1.0) {
 | 
				
			||||||
 | 
					    samples = multiply(array(scale, dtype), samples, stream);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (loc != 0.0) {
 | 
				
			||||||
 | 
					    samples = add(array(loc, dtype), samples, stream);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return samples;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
array randint(
 | 
					array randint(
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								mlx/random.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								mlx/random.h
									
									
									
									
									
								
							@@ -95,13 +95,30 @@ inline array uniform(
 | 
				
			|||||||
array normal(
 | 
					array normal(
 | 
				
			||||||
    const std::vector<int>& shape,
 | 
					    const std::vector<int>& shape,
 | 
				
			||||||
    Dtype dtype,
 | 
					    Dtype dtype,
 | 
				
			||||||
 | 
					    const float loc,
 | 
				
			||||||
 | 
					    const float scale,
 | 
				
			||||||
    const std::optional<array>& key = std::nullopt,
 | 
					    const std::optional<array>& key = std::nullopt,
 | 
				
			||||||
    StreamOrDevice s = {});
 | 
					    StreamOrDevice s = {});
 | 
				
			||||||
inline array normal(
 | 
					inline array normal(
 | 
				
			||||||
    const std::vector<int>& shape,
 | 
					    const std::vector<int>& shape,
 | 
				
			||||||
 | 
					    const float loc,
 | 
				
			||||||
 | 
					    const float scale,
 | 
				
			||||||
    const std::optional<array>& key = std::nullopt,
 | 
					    const std::optional<array>& key = std::nullopt,
 | 
				
			||||||
    StreamOrDevice s = {}) {
 | 
					    StreamOrDevice s = {}) {
 | 
				
			||||||
  return normal(shape, float32, key, s);
 | 
					  return normal(shape, float32, loc, scale, key, s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline array normal(
 | 
				
			||||||
 | 
					    const std::vector<int>& shape,
 | 
				
			||||||
 | 
					    const Dtype dtype,
 | 
				
			||||||
 | 
					    const std::optional<array>& key = std::nullopt,
 | 
				
			||||||
 | 
					    StreamOrDevice s = {}) {
 | 
				
			||||||
 | 
					  return normal(shape, dtype, 0.0, 1.0, key, s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline array normal(
 | 
				
			||||||
 | 
					    const std::vector<int>& shape,
 | 
				
			||||||
 | 
					    const std::optional<array>& key = std::nullopt,
 | 
				
			||||||
 | 
					    StreamOrDevice s = {}) {
 | 
				
			||||||
 | 
					  return normal(shape, float32, 0.0, 1.0, key, s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Generate integer samples uniformly at random */
 | 
					/** Generate integer samples uniformly at random */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,13 +99,17 @@ void init_random(py::module_& parent_module) {
 | 
				
			|||||||
      "normal",
 | 
					      "normal",
 | 
				
			||||||
      [](const std::vector<int>& shape,
 | 
					      [](const std::vector<int>& shape,
 | 
				
			||||||
         std::optional<Dtype> type,
 | 
					         std::optional<Dtype> type,
 | 
				
			||||||
 | 
					         float loc,
 | 
				
			||||||
 | 
					         float scale,
 | 
				
			||||||
         const std::optional<array>& key,
 | 
					         const std::optional<array>& key,
 | 
				
			||||||
         StreamOrDevice s) {
 | 
					         StreamOrDevice s) {
 | 
				
			||||||
        return normal(shape, type.value_or(float32), key, s);
 | 
					        return normal(shape, type.value_or(float32), loc, scale, key, s);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      "shape"_a = std::vector<int>{},
 | 
					      "shape"_a = std::vector<int>{},
 | 
				
			||||||
      "dtype"_a = std::optional{float32},
 | 
					      "dtype"_a = std::optional{float32},
 | 
				
			||||||
 | 
					      "loc"_a = 0.0,
 | 
				
			||||||
 | 
					      "scale"_a = 1.0,
 | 
				
			||||||
      "key"_a = none,
 | 
					      "key"_a = none,
 | 
				
			||||||
      "stream"_a = none,
 | 
					      "stream"_a = none,
 | 
				
			||||||
      R"pbdoc(
 | 
					      R"pbdoc(
 | 
				
			||||||
@@ -114,6 +118,8 @@ void init_random(py::module_& parent_module) {
 | 
				
			|||||||
        Args:
 | 
					        Args:
 | 
				
			||||||
            shape (list(int), optional): Shape of the output. Default is ``()``.
 | 
					            shape (list(int), optional): Shape of the output. Default is ``()``.
 | 
				
			||||||
            dtype (Dtype, optional): Type of the output. Default is ``float32``.
 | 
					            dtype (Dtype, optional): Type of the output. Default is ``float32``.
 | 
				
			||||||
 | 
					            loc (float, optional): Mean of the distribution. Default is ``0.0``.
 | 
				
			||||||
 | 
					            scale (float, optional): Standard deviation of the distribution. Default is ``1.0``.
 | 
				
			||||||
            key (array, optional): A PRNG key. Default: None.
 | 
					            key (array, optional): A PRNG key. Default: None.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,6 +80,20 @@ class TestRandom(mlx_tests.MLXTestCase):
 | 
				
			|||||||
            a = mx.random.normal(dtype=t)
 | 
					            a = mx.random.normal(dtype=t)
 | 
				
			||||||
            self.assertEqual(a.dtype, t)
 | 
					            self.assertEqual(a.dtype, t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Generate with a given mean and standard deviation
 | 
				
			||||||
 | 
					        loc = 1.0
 | 
				
			||||||
 | 
					        scale = 2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        a = mx.random.normal(shape=(3, 2), loc=loc, scale=scale, key=key)
 | 
				
			||||||
 | 
					        b = scale * mx.random.normal(shape=(3, 2), key=key) + loc
 | 
				
			||||||
 | 
					        self.assertTrue(mx.allclose(a, b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        a = mx.random.normal(
 | 
				
			||||||
 | 
					            shape=(3, 2), loc=loc, scale=scale, dtype=mx.float16, key=key
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        b = scale * mx.random.normal(shape=(3, 2), dtype=mx.float16, key=key) + loc
 | 
				
			||||||
 | 
					        self.assertTrue(mx.allclose(a, b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(mx.random.normal().dtype, mx.random.normal(dtype=None).dtype)
 | 
					        self.assertEqual(mx.random.normal().dtype, mx.random.normal(dtype=None).dtype)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_randint(self):
 | 
					    def test_randint(self):
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user