@@ -309,12 +309,26 @@ func testCasesWithinTolerance[N Int[N]](t *testing.T) {
309
309
},
310
310
}
311
311
312
+ // Create a zero coefficient to test the error case.
313
+ zeroCoefficient := NewInt [N ]().FromUint64 (0 )
314
+
312
315
// Run the test cases.
313
316
for idx , tc := range testCases {
314
- result := tc .firstFp .WithinTolerance (
317
+ result , err := tc .firstFp .WithinTolerance (
315
318
tc .secondFp , NewInt [N ]().FromUint64 (tc .tolerancePpm ),
316
319
)
317
320
321
+ // If either of the coefficients are zero, we expect an error.
322
+ if tc .firstFp .Coefficient .Equals (zeroCoefficient ) ||
323
+ tc .secondFp .Coefficient .Equals (zeroCoefficient ) {
324
+
325
+ require .Error (t , err )
326
+ require .False (t , result )
327
+ continue
328
+ }
329
+
330
+ require .NoError (t , err , "Test case %d failed" , idx )
331
+
318
332
// Compare bounds check result with expected test case within
319
333
// bounds flag.
320
334
require .Equal (
@@ -330,7 +344,7 @@ func testWithinToleranceEqualValues(t *rapid.T) {
330
344
tolerancePpm := rapid .Int64Min (0 ).Draw (t , "tolerance" )
331
345
332
346
// Generate a random coefficient and scale.
333
- coefficient := rapid .Int64Min (0 ).Draw (t , "coefficient" )
347
+ coefficient := rapid .Int64Min (1 ).Draw (t , "coefficient" )
334
348
scale := rapid .Uint8Range (0 , 18 ).Draw (t , "scale" )
335
349
336
350
// Create two identical FixedPoint[BigInt] values.
@@ -348,7 +362,9 @@ func testWithinToleranceEqualValues(t *rapid.T) {
348
362
349
363
// The result should always be true when the fixed-point values
350
364
// are equal.
351
- result := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
365
+ result , err := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
366
+ require .NoError (t , err )
367
+
352
368
if ! result {
353
369
t .Fatalf ("WithinTolerance should be true when values " +
354
370
"are equal, but got false" )
@@ -363,7 +379,7 @@ func testWithinToleranceZeroTolerance(t *rapid.T) {
363
379
tolerancePpmBigInt := NewBigInt (big .NewInt (0 ))
364
380
365
381
// Generate two equal fixed-points.
366
- coefficient := rapid .Int64Min (0 ).Draw (t , "coefficient" )
382
+ coefficient := rapid .Int64Min (1 ).Draw (t , "coefficient" )
367
383
scale := rapid .Uint8Range (0 , 18 ).Draw (t , "scale" )
368
384
f1 := FixedPoint [BigInt ]{
369
385
Coefficient : NewBigInt (big .NewInt (coefficient )),
@@ -375,16 +391,18 @@ func testWithinToleranceZeroTolerance(t *rapid.T) {
375
391
Scale : scale ,
376
392
}
377
393
378
- require .True (t , f1 .WithinTolerance (f2 , tolerancePpmBigInt ))
394
+ result , err := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
395
+ require .NoError (t , err )
396
+ require .True (t , result )
379
397
}
380
398
381
399
// testWithinToleranceSymmetric is a property-based test which ensures that the
382
400
// WithinTolerance method is symmetric (swapping the order of the fixed-point
383
401
// values does not change the result).
384
402
func testWithinToleranceSymmetric (t * rapid.T ) {
385
403
// Generate random coefficients, scales, and tolerance
386
- coefficient := rapid .Int64Min (0 ).Draw (t , "coefficient_1" )
387
- coefficient2 := rapid .Int64Min (0 ).Draw (t , "coefficient_2" )
404
+ coefficient := rapid .Int64Min (1 ).Draw (t , "coefficient_1" )
405
+ coefficient2 := rapid .Int64Min (1 ).Draw (t , "coefficient_2" )
388
406
scale1 := rapid .Uint8Range (0 , 18 ).Draw (t , "scale_1" )
389
407
scale2 := rapid .Uint8Range (0 , 18 ).Draw (t , "scale_2" )
390
408
tolerancePpm := rapid .Int64Range (0 , 1_000_000 ).Draw (t , "tolerance" )
@@ -401,8 +419,11 @@ func testWithinToleranceSymmetric(t *rapid.T) {
401
419
402
420
tolerancePpmBigInt := NewBigInt (big .NewInt (tolerancePpm ))
403
421
404
- result1 := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
405
- result2 := f2 .WithinTolerance (f1 , tolerancePpmBigInt )
422
+ result1 , err := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
423
+ require .NoError (t , err )
424
+
425
+ result2 , err := f2 .WithinTolerance (f1 , tolerancePpmBigInt )
426
+ require .NoError (t , err )
406
427
407
428
if result1 != result2 {
408
429
t .Fatalf ("WithinTolerance is not symmetric: " +
@@ -420,14 +441,14 @@ func testWithinToleranceMaxTolerance(t *rapid.T) {
420
441
tolerancePpmBigInt := NewBigInt (big .NewInt (tolerancePpm ))
421
442
422
443
// Generate random fixed-point values.
423
- coefficient1 := rapid .Int64Min (0 ).Draw (t , "coefficient_1" )
444
+ coefficient1 := rapid .Int64Min (1 ).Draw (t , "coefficient_1" )
424
445
scale1 := rapid .Uint8Range (0 , 18 ).Draw (t , "scale_1" )
425
446
f1 := FixedPoint [BigInt ]{
426
447
Coefficient : NewBigInt (big .NewInt (coefficient1 )),
427
448
Scale : scale1 ,
428
449
}
429
450
430
- coefficient2 := rapid .Int64Min (0 ).Draw (t , "coefficient_2" )
451
+ coefficient2 := rapid .Int64Min (1 ).Draw (t , "coefficient_2" )
431
452
scale2 := rapid .Uint8Range (0 , 18 ).Draw (t , "scale_2" )
432
453
f2 := FixedPoint [BigInt ]{
433
454
Coefficient : NewBigInt (big .NewInt (coefficient2 )),
@@ -436,13 +457,59 @@ func testWithinToleranceMaxTolerance(t *rapid.T) {
436
457
437
458
// The result should always be true when tolerancePpm is at its max or
438
459
// larger.
439
- result := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
460
+ result , err := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
461
+ require .NoError (t , err )
462
+
440
463
if ! result {
441
464
t .Fatalf ("WithinTolerance should be true when tolerancePpm " +
442
465
"is large, but got false" )
443
466
}
444
467
}
445
468
469
+ // testWithinToleranceCoefficientZeroError is a property-based test which
470
+ // ensures that the WithinTolerance method returns an error when either or both
471
+ // of the fixed-point values have a coefficient of zero.
472
+ func testWithinToleranceCoefficientZeroError (t * rapid.T ) {
473
+ // Set tolerancePpm to any value above 100%.
474
+ tolerancePpm := rapid .Int64Min (1_000_000 ).Draw (t , "tolerance" )
475
+ tolerancePpmBigInt := NewBigInt (big .NewInt (tolerancePpm ))
476
+
477
+ // Generate a random mode to determine which coefficient(s) to set to
478
+ // zero.
479
+ mode := rapid .Int64Range (0 , 2 ).Draw (t , "mode" )
480
+
481
+ var coefficient1 , coefficient2 int64
482
+ switch mode {
483
+ case 0 :
484
+ coefficient1 = 0
485
+ coefficient2 = rapid .Int64Min (1 ).Draw (t , "coefficient_2" )
486
+ case 1 :
487
+ coefficient1 = rapid .Int64Min (1 ).Draw (t , "coefficient_1" )
488
+ coefficient2 = 0
489
+ case 2 :
490
+ coefficient1 = 0
491
+ coefficient2 = 0
492
+ }
493
+
494
+ // Generate random fixed-point values from the coefficients.
495
+ scale1 := rapid .Uint8Range (0 , 18 ).Draw (t , "scale_1" )
496
+ f1 := FixedPoint [BigInt ]{
497
+ Coefficient : NewBigInt (big .NewInt (coefficient1 )),
498
+ Scale : scale1 ,
499
+ }
500
+
501
+ scale2 := rapid .Uint8Range (0 , 18 ).Draw (t , "scale_2" )
502
+ f2 := FixedPoint [BigInt ]{
503
+ Coefficient : NewBigInt (big .NewInt (coefficient2 )),
504
+ Scale : scale2 ,
505
+ }
506
+
507
+ // We always expect an error when either or both coefficients are zero.
508
+ result , err := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
509
+ require .Error (t , err )
510
+ require .False (t , result )
511
+ }
512
+
446
513
// testWithinToleranceFloatReproduce is a property-based test that verifies
447
514
// the reproducibility of the WithinTolerance method's result using calculations
448
515
// on float64 values.
@@ -452,7 +519,7 @@ func testWithinToleranceFloatReproduce(t *rapid.T) {
452
519
tolerancePpmBigInt := NewBigInt (big .NewInt (tolerancePpm ))
453
520
454
521
// Generate random fixed-point values.
455
- coefficientsRange := rapid .Int64Range (0 , 1_000_000_000 )
522
+ coefficientsRange := rapid .Int64Range (1 , 1_000_000_000 )
456
523
457
524
coefficient1 := coefficientsRange .Draw (t , "coefficient_1" )
458
525
scale1 := rapid .Uint8Range (0 , 9 ).Draw (t , "scale_1" )
@@ -469,7 +536,8 @@ func testWithinToleranceFloatReproduce(t *rapid.T) {
469
536
}
470
537
471
538
// Compute the result using the WithinTolerance method.
472
- result := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
539
+ result , err := f1 .WithinTolerance (f2 , tolerancePpmBigInt )
540
+ require .NoError (t , err )
473
541
474
542
// Compute expected result using float64.
475
543
f1Float := f1 .ToFloat64 ()
@@ -523,6 +591,11 @@ func testWithinTolerance(t *testing.T) {
523
591
rapid .MakeCheck (testWithinToleranceMaxTolerance ),
524
592
)
525
593
594
+ t .Run (
595
+ "within_tolerance_coefficient_zero_error" ,
596
+ rapid .MakeCheck (testWithinToleranceCoefficientZeroError ),
597
+ )
598
+
526
599
t .Run (
527
600
"within_tolerance_float_reproduce" ,
528
601
rapid .MakeCheck (testWithinToleranceFloatReproduce ),
0 commit comments