Skip to content

Commit

Permalink
Rng.uniform,gaussian,next returns a Stream now
Browse files Browse the repository at this point in the history
  • Loading branch information
rainyl committed Jun 30, 2024
1 parent a7b6eca commit 4569cda
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 48 deletions.
62 changes: 40 additions & 22 deletions lib/src/core/rng.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,43 +59,61 @@ class Rng extends CvStruct<cvg.RNG> {
/// That is, the mean value of the returned random numbers is zero and
/// the standard deviation is the specified sigma .
/// https://docs.opencv.org/4.x/d1/dd6/classcv_1_1RNG.html#a8df8ce4dc7d15916cee743e5a884639d
double gaussian(double sigma) {
return cvRunArena((arena) {
final p = arena<ffi.Double>();
Stream<double> gaussian(double sigma, {int? maxCount}) async* {
int count = 0;
while (true) {
final p = calloc<ffi.Double>();
cvRun(() => CFFI.RNG_Gaussian(ref, sigma, p));
return p.value;
});
final v = p.value;
calloc.free(p);
yield v;

count++;
if (count == maxCount) break;
}
}

/// The method updates the state using the MWC algorithm and returns the next 32-bit random number.
/// https://docs.opencv.org/4.x/d1/dd6/classcv_1_1RNG.html#ad8d035897a5e31e7fc3e1e6c378c32f5
int next() {
return cvRunArena<int>((arena) {
final p = arena<ffi.Uint32>();
Stream<int> next({int? maxCount}) async* {
int count = 0;
while (true) {
final p = calloc<ffi.Uint32>();
cvRun(() => CFFI.RNG_Next(ref, p));
return p.value;
});
final v = p.value;
calloc.free(p);
yield v;

count++;
if (count == maxCount) break;
}
}

/// returns uniformly distributed integer random number from [a,b) range
/// The methods transform the state using the MWC algorithm and return the next
/// uniformly-distributed random number of the specified type, deduced from
/// the input parameter type, from the range [a, b) .
/// https://docs.opencv.org/4.x/d1/dd6/classcv_1_1RNG.html#a8325cc562269b47bcac2343639b6fafc
T uniform<T>(T a, T b) {
return cvRunArena<T>((arena) {
if (T == int) {
final p = arena<ffi.Int>();
cvRun(() => CFFI.RNG_Uniform(ref, a as int, b as int, p));
return p.value as T;
} else if (T == double) {
final p = arena<ffi.Double>();
cvRun(() => CFFI.RNG_UniformDouble(ref, a as double, b as double, p));
return p.value as T;
Stream<num> uniform(num a, num b, {int? maxCount}) async* {
int count = 0;
while (true) {
if (a is int && b is int) {
final p = calloc<ffi.Int>();
cvRun(() => CFFI.RNG_Uniform(ref, a, b, p));
final v = p.value;
calloc.free(p);
yield v;
} else {
throw UnsupportedError("Unsupported type $T");
final p = calloc<ffi.Double>();
cvRun(() => CFFI.RNG_UniformDouble(ref, a.toDouble(), b.toDouble(), p));
final v = p.value;
calloc.free(p);
yield v;
}
});

count++;
if (count == maxCount) break;
}
}

@override
Expand Down
52 changes: 37 additions & 15 deletions lib/src/core/rng_async.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,40 +48,62 @@ extension RngAsync on Rng {
/// That is, the mean value of the returned random numbers is zero and
/// the standard deviation is the specified sigma .
/// https://docs.opencv.org/4.x/d1/dd6/classcv_1_1RNG.html#a8df8ce4dc7d15916cee743e5a884639d
Future<double> gaussianAsync(double sigma) async => cvRunAsync(
Stream<double> gaussianAsync(double sigma, {int? maxCount}) async* {
int count = 0;
while (true) {
final v = await cvRunAsync<double>(
(callback) => CFFI.RNG_Gaussian_Async(ref, sigma, callback),
doubleCompleter,
);
yield v;

count++;
if (count == maxCount) break;
}
}

/// The method updates the state using the MWC algorithm and returns the next 32-bit random number.
/// https://docs.opencv.org/4.x/d1/dd6/classcv_1_1RNG.html#ad8d035897a5e31e7fc3e1e6c378c32f5
Future<int> nextAsync() async => cvRunAsync(
Stream<int> nextAsync({int? maxCount}) async* {
int count = 0;
while (true) {
final v = await cvRunAsync<int>(
(callback) => CFFI.RNG_Next_Async(ref, callback),
(c, p) {
final rval = p.cast<ffi.Uint32>().value;
calloc.free(p);
c.complete(rval);
},
);
yield v;

count++;
if (count == maxCount) break;
}
}

/// returns uniformly distributed integer random number from [a,b) range
/// The methods transform the state using the MWC algorithm and return the next
/// uniformly-distributed random number of the specified type, deduced from
/// the input parameter type, from the range [a, b) .
/// https://docs.opencv.org/4.x/d1/dd6/classcv_1_1RNG.html#a8325cc562269b47bcac2343639b6fafc
Future<T> uniformAsync<T>(T a, T b) async {
if (T == int) {
final rval =
cvRunAsync((callback) => CFFI.RNG_Uniform_Async(ref, a as int, b as int, callback), intCompleter);
return rval as Future<T>;
} else if (T == double) {
final rval = cvRunAsync(
(callback) => CFFI.RNG_UniformDouble_Async(ref, a as double, b as double, callback),
doubleCompleter,
);
return rval as Future<T>;
} else {
throw UnsupportedError("Unsupported type $T");
Stream<num> uniformAsync(num a, num b, {int? maxCount}) async* {
int count = 0;
while (true) {
if (a is int && b is int) {
final rval =
await cvRunAsync<int>((callback) => CFFI.RNG_Uniform_Async(ref, a, b, callback), intCompleter);
yield rval;
} else {
final rval = await cvRunAsync<double>(
(callback) => CFFI.RNG_UniformDouble_Async(ref, a.toDouble(), b.toDouble(), callback),
doubleCompleter,
);
yield rval;
}

count++;
if (count == maxCount) break;
}
}
}
10 changes: 5 additions & 5 deletions test/core/rng_async_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import 'package:test/test.dart';
void main() async {
test("cv.RNG", () async {
final rng = await cv.RngAsync.createAsync();
final v = List.generate(100000, (index) => rng.uniform(0, 241));
final v = await rng.uniformAsync(0, 241, maxCount: 10000).take(10000).toList();
expect(v, everyElement(greaterThanOrEqualTo(0)));
final v1 = List.generate(100000, (index) => rng.uniform<double>(2.41, 241.0));
final v1 = await rng.uniformAsync(2.41, 241.0).take(10000).toList();
expect(v1, everyElement(greaterThanOrEqualTo(2.41)));

rng.dispose();
});

test("cv.RNG.fromSeed", () async {
final rng = await cv.RngAsync.fromSeedAsync(241);
final v = List.generate(100000, (index) => rng.gaussian(2.41));
expect(v.length, equals(100000));
final v = await rng.gaussianAsync(2.41).take(10000).toList();
expect(v.length, equals(10000));

final v1 = await rng.nextAsync();
final v1 = await rng.nextAsync().first;
expect(v1, isA<int>());

final rng1 = cv.Rng.fromSeed(241);
Expand Down
12 changes: 6 additions & 6 deletions test/core/rng_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ import 'package:opencv_dart/opencv_dart.dart' as cv;
import 'package:test/test.dart';

void main() {
test("cv.RNG", () {
test("cv.RNG", () async {
final rng = cv.Rng();
final v = List.generate(100000, (index) => rng.uniform(0, 241));
final v = await rng.uniformAsync(0, 241, maxCount: 100000).take(10000).toList();
expect(v, everyElement(greaterThanOrEqualTo(0)));
final v1 = List.generate(100000, (index) => rng.uniform<double>(2.41, 241.0));
final v1 = await rng.uniformAsync(2.41, 241.0).take(100000).toList();
expect(v1, everyElement(greaterThanOrEqualTo(2.41)));

rng.dispose();
});

test("cv.RNG.fromSeed", () {
test("cv.RNG.fromSeed", () async {
final rng = cv.Rng.fromSeed(241);
final v = List.generate(100000, (index) => rng.gaussian(2.41));
final v = await rng.gaussian(2.41).take(100000).toList();
expect(v.length, equals(100000));

final v1 = rng.next();
final v1 = await rng.next().first;
expect(v1, isA<int>());

final rng1 = cv.Rng.fromSeed(241);
Expand Down

0 comments on commit 4569cda

Please sign in to comment.