CCSDS 121.0-B-3 Lossless Data Compression (Rice/Golomb coding)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

rice: extract encode/decode helpers, add test runner + fuzz mli

Split encode_ccsds_block into best_split_k/encode_second_extension/
encode_uncompressed/encode_split. Pull decode_zero_blocks/decode_second
_extension/decode_uncompressed/decode_split out of decode_ccsds_blocks.
Compress now delegates each block to encode_one_block and a
count_zero_run helper; decompress factors out decode_rsi /
decompress_blocks. Move Alcotest.run from test_rice.ml into a new
test.ml exporting the rice suite. Add fuzz_rice.mli interface.

+238 -233
+4
fuzz/fuzz_rice.mli
··· 1 + (** Fuzz tests for {!Rice}. *) 2 + 3 + val suite : string * Alcobar.test_case list 4 + (** Test suite. *)
+201 -197
lib/rice.ml
··· 359 359 in 360 360 Bitwriter.write_unary bw fs 361 361 362 + let best_split_k residuals res_ofs count id_len bps is_ref kmax = 363 + let best_k = ref 0 in 364 + let best_len = ref max_int in 365 + for k = 0 to kmax do 366 + let l = split_encoded_len residuals res_ofs count k in 367 + let total = id_len + (if is_ref then bps else 0) + l in 368 + if total < !best_len then begin 369 + best_k := k; 370 + best_len := total 371 + end 372 + done; 373 + (!best_k, !best_len) 374 + 375 + let encode_second_extension bw residuals res_ofs count bps id_len is_ref 376 + ref_sample = 377 + Bitwriter.write_bits bw (id_len + 1) 1; 378 + if is_ref then Bitwriter.write_bits bw bps ref_sample; 379 + let i = ref res_ofs in 380 + while !i < res_ofs + count do 381 + let a = residuals.(!i) in 382 + let b = residuals.(!i + 1) in 383 + let d = a + b in 384 + let fs_val = (d * (d + 1) / 2) + b in 385 + Bitwriter.write_unary bw fs_val; 386 + i := !i + 2 387 + done 388 + 389 + let encode_uncompressed bw residuals res_ofs count bps id_len is_ref ref_sample 390 + = 391 + let uncomp_id = (1 lsl id_len) - 1 in 392 + Bitwriter.write_bits bw id_len uncomp_id; 393 + if is_ref then Bitwriter.write_bits bw bps ref_sample; 394 + for i = res_ofs to res_ofs + count - 1 do 395 + Bitwriter.write_bits bw bps residuals.(i) 396 + done 397 + 398 + let encode_split bw residuals res_ofs count bps id_len is_ref ref_sample k = 399 + Bitwriter.write_bits bw id_len (k + 1); 400 + if is_ref then Bitwriter.write_bits bw bps ref_sample; 401 + for i = res_ofs to res_ofs + count - 1 do 402 + let m = residuals.(i) in 403 + let q = m lsr k in 404 + let r = m land ((1 lsl k) - 1) in 405 + Bitwriter.write_unary bw q; 406 + Bitwriter.write_bits bw k r 407 + done 408 + 362 409 let encode_ccsds_block bw residuals ofs len bps id_len is_ref ref_sample = 363 410 let kmax = kmax_of_id_len id_len in 364 411 let count = if is_ref then len - 1 else len in 365 412 let res_ofs = if is_ref then ofs + 1 else ofs in 366 413 (* Check for zero block: all (non-reference) residuals are zero *) 367 - if count > 0 && all_zero residuals res_ofs count then begin 368 - encode_zero_blocks bw bps id_len is_ref ref_sample 1 1 369 - end 370 - else if count = 0 then begin 414 + if count = 0 || (count > 0 && all_zero residuals res_ofs count) then 371 415 encode_zero_blocks bw bps id_len is_ref ref_sample 1 1 372 - end 373 - else begin 374 - (* Try all split options and pick the best *) 375 - let best_k = ref 0 in 376 - let best_len = ref max_int in 377 - for k = 0 to kmax do 378 - let l = split_encoded_len residuals res_ofs count k in 379 - let total = id_len + (if is_ref then bps else 0) + l in 380 - if total < !best_len then begin 381 - best_k := k; 382 - best_len := total 383 - end 384 - done; 385 - (* Also try second extension *) 416 + else 417 + let best_k, best_len = 418 + best_split_k residuals res_ofs count id_len bps is_ref kmax 419 + in 386 420 let se_len = se_encoded_len residuals res_ofs count in 387 421 let se_total = 388 422 if se_len = max_int then max_int 389 423 else id_len + 1 + (if is_ref then bps else 0) + se_len 390 424 in 391 - (* Also try uncompressed *) 392 425 let uncomp_total = id_len + (if is_ref then bps else 0) + (count * bps) in 393 - if se_total < !best_len && se_total <= uncomp_total then begin 394 - (* Second extension *) 395 - Bitwriter.write_bits bw (id_len + 1) 1; 396 - if is_ref then Bitwriter.write_bits bw bps ref_sample; 397 - let i = ref res_ofs in 398 - while !i < res_ofs + count do 399 - let a = residuals.(!i) in 400 - let b = residuals.(!i + 1) in 401 - let d = a + b in 402 - let fs_val = (d * (d + 1) / 2) + b in 403 - Bitwriter.write_unary bw fs_val; 404 - i := !i + 2 405 - done 406 - end 407 - else if uncomp_total < !best_len then begin 408 - (* Uncompressed *) 409 - let uncomp_id = (1 lsl id_len) - 1 in 410 - Bitwriter.write_bits bw id_len uncomp_id; 411 - if is_ref then Bitwriter.write_bits bw bps ref_sample; 412 - for i = res_ofs to res_ofs + count - 1 do 413 - Bitwriter.write_bits bw bps residuals.(i) 414 - done 415 - end 416 - else begin 417 - (* Split coding with best k *) 418 - let k = !best_k in 419 - Bitwriter.write_bits bw id_len (k + 1); 420 - if is_ref then Bitwriter.write_bits bw bps ref_sample; 421 - for i = res_ofs to res_ofs + count - 1 do 422 - let m = residuals.(i) in 423 - let q = m lsr k in 424 - let r = m land ((1 lsl k) - 1) in 425 - Bitwriter.write_unary bw q; 426 - Bitwriter.write_bits bw k r 427 - done 428 - end 429 - end 426 + if se_total < best_len && se_total <= uncomp_total then 427 + encode_second_extension bw residuals res_ofs count bps id_len is_ref 428 + ref_sample 429 + else if uncomp_total < best_len then 430 + encode_uncompressed bw residuals res_ofs count bps id_len is_ref 431 + ref_sample 432 + else 433 + encode_split bw residuals res_ofs count bps id_len is_ref ref_sample 434 + best_k 435 + 436 + let decode_zero_blocks br block_size bps is_ref out out_pos blocks_remaining = 437 + let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 438 + let fs = Bitreader.read_unary br in 439 + let zero_blocks = fs + 1 in 440 + let zero_blocks = 441 + if zero_blocks = 5 then blocks_remaining (* rest of segment *) 442 + else if zero_blocks > 5 then zero_blocks - 1 443 + else zero_blocks 444 + in 445 + let zero_blocks = min zero_blocks blocks_remaining in 446 + if is_ref then out.(out_pos) <- ref_sample; 447 + let total_samples = zero_blocks * block_size in 448 + for i = 0 to total_samples - 1 do 449 + if not (is_ref && i = 0) then out.(out_pos + i) <- 0 450 + done; 451 + zero_blocks 452 + 453 + let decode_second_extension br block_size bps is_ref out out_pos = 454 + let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 455 + if is_ref then out.(out_pos) <- ref_sample; 456 + let count = if is_ref then block_size - 1 else block_size in 457 + let res_ofs = out_pos + if is_ref then 1 else 0 in 458 + let i = ref 0 in 459 + while !i < count do 460 + let fs_val = Bitreader.read_unary br in 461 + let d = ref 0 in 462 + while (!d + 1) * (!d + 2) / 2 <= fs_val do 463 + incr d 464 + done; 465 + let b = fs_val - (!d * (!d + 1) / 2) in 466 + let a = !d - b in 467 + out.(res_ofs + !i) <- a; 468 + if !i + 1 < count then out.(res_ofs + !i + 1) <- b; 469 + i := !i + 2 470 + done; 471 + 1 472 + 473 + let decode_uncompressed br block_size bps is_ref out out_pos = 474 + let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 475 + if is_ref then out.(out_pos) <- ref_sample; 476 + let count = if is_ref then block_size - 1 else block_size in 477 + let res_ofs = out_pos + if is_ref then 1 else 0 in 478 + for i = 0 to count - 1 do 479 + out.(res_ofs + i) <- Bitreader.read_bits br bps 480 + done; 481 + 1 482 + 483 + let decode_split br block_size bps is_ref out out_pos k = 484 + let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 485 + if is_ref then out.(out_pos) <- ref_sample; 486 + let count = if is_ref then block_size - 1 else block_size in 487 + let res_ofs = out_pos + if is_ref then 1 else 0 in 488 + for i = 0 to count - 1 do 489 + let q = Bitreader.read_unary br in 490 + let r = if k > 0 then Bitreader.read_bits br k else 0 in 491 + out.(res_ofs + i) <- (q lsl k) lor r 492 + done; 493 + 1 430 494 431 495 (** Decode one or more CCSDS blocks. Writes residuals into [out] starting at 432 496 [out_pos]. [is_ref] indicates whether the first decoded block starts an RSI. ··· 436 500 blocks_remaining = 437 501 let id = Bitreader.read_bits br id_len in 438 502 let max_id = (1 lsl id_len) - 1 in 439 - if id = 0 then begin 440 - (* Low entropy: read one more bit *) 503 + if id = 0 then 441 504 let sub = Bitreader.read_bit br in 442 - if sub = 0 then begin 443 - (* Zero block *) 444 - let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 445 - (* Read FS for zero block count *) 446 - let fs = Bitreader.read_unary br in 447 - let zero_blocks = fs + 1 in 448 - (* If zero_blocks >= 5 (ROS encoding), adjust *) 449 - let zero_blocks = 450 - if zero_blocks = 5 then blocks_remaining (* rest of segment *) 451 - else if zero_blocks > 5 then zero_blocks - 1 452 - else zero_blocks 453 - in 454 - let zero_blocks = min zero_blocks blocks_remaining in 455 - (* Fill zero blocks: first block may have reference *) 456 - if is_ref then out.(out_pos) <- ref_sample; 457 - (* All other positions in all zero blocks are already 0 (from Array.make) 458 - but let's be explicit for blocks beyond the first *) 459 - let total_samples = zero_blocks * block_size in 460 - for i = 0 to total_samples - 1 do 461 - if not (is_ref && i = 0) then out.(out_pos + i) <- 0 462 - done; 463 - zero_blocks 464 - end 465 - else begin 466 - (* Second extension *) 467 - let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 468 - if is_ref then out.(out_pos) <- ref_sample; 469 - let count = if is_ref then block_size - 1 else block_size in 470 - let res_ofs = out_pos + if is_ref then 1 else 0 in 471 - (* Decode pairs *) 472 - let i = ref 0 in 473 - while !i < count do 474 - let fs_val = Bitreader.read_unary br in 475 - (* Recover d such that d*(d+1)/2 <= fs_val *) 476 - let d = ref 0 in 477 - while (!d + 1) * (!d + 2) / 2 <= fs_val do 478 - incr d 479 - done; 480 - let b = fs_val - (!d * (!d + 1) / 2) in 481 - let a = !d - b in 482 - out.(res_ofs + !i) <- a; 483 - if !i + 1 < count then out.(res_ofs + !i + 1) <- b; 484 - i := !i + 2 485 - done; 486 - 1 487 - end 488 - end 489 - else if id = max_id then begin 490 - (* Uncompressed *) 491 - let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 492 - if is_ref then out.(out_pos) <- ref_sample; 493 - let count = if is_ref then block_size - 1 else block_size in 494 - let res_ofs = out_pos + if is_ref then 1 else 0 in 495 - for i = 0 to count - 1 do 496 - out.(res_ofs + i) <- Bitreader.read_bits br bps 497 - done; 498 - 1 505 + if sub = 0 then 506 + decode_zero_blocks br block_size bps is_ref out out_pos blocks_remaining 507 + else decode_second_extension br block_size bps is_ref out out_pos 508 + else if id = max_id then 509 + decode_uncompressed br block_size bps is_ref out out_pos 510 + else decode_split br block_size bps is_ref out out_pos (id - 1) 511 + 512 + (* -- Compress ------------------------------------------------------------- *) 513 + 514 + let count_zero_run residuals block_idx b blocks_per_rsi total_blocks j = 515 + let run = ref 1 in 516 + while 517 + b + !run < blocks_per_rsi 518 + && block_idx + b + !run < total_blocks 519 + && is_zero_block residuals ((block_idx + b + !run) * j) j false 520 + do 521 + incr run 522 + done; 523 + !run 524 + 525 + let encode_one_block bw residuals samples j bps id_len blocks_per_rsi 526 + total_blocks block_idx b = 527 + let global_block = block_idx + b in 528 + let ofs = global_block * j in 529 + let is_ref = b = 0 in 530 + let ref_sample = if is_ref then samples.(ofs) else 0 in 531 + if is_zero_block residuals ofs j is_ref then begin 532 + let run = 533 + count_zero_run residuals block_idx b blocks_per_rsi total_blocks j 534 + in 535 + let blocks_remaining = min blocks_per_rsi (total_blocks - block_idx) - b in 536 + encode_zero_blocks bw bps id_len is_ref ref_sample run blocks_remaining; 537 + run 499 538 end 500 539 else begin 501 - (* Split coding with k = id - 1 *) 502 - let k = id - 1 in 503 - let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in 504 - if is_ref then out.(out_pos) <- ref_sample; 505 - let count = if is_ref then block_size - 1 else block_size in 506 - let res_ofs = out_pos + if is_ref then 1 else 0 in 507 - for i = 0 to count - 1 do 508 - let q = Bitreader.read_unary br in 509 - let r = if k > 0 then Bitreader.read_bits br k else 0 in 510 - out.(res_ofs + i) <- (q lsl k) lor r 511 - done; 540 + encode_ccsds_block bw residuals ofs j bps id_len is_ref ref_sample; 512 541 1 513 542 end 514 543 515 - (* -- Compress ------------------------------------------------------------- *) 516 - 517 544 let compress cfg data = 518 545 let bps = cfg.bits_per_sample in 519 546 let bps_bytes = bytes_per_sample bps in 520 547 let n = sample_count cfg (Bytes.length data) in 521 548 if n = 0 then Bytes.empty 522 - else begin 549 + else 523 550 let j = cfg.block_size in 524 551 (* Pad sample count to a multiple of block_size (CCSDS requires full 525 552 blocks; the last block is zero-padded as in libaec). *) 526 553 let n_padded = (n + j - 1) / j * j in 527 - (* Read samples from input, zero-pad the remainder *) 528 554 let samples = 529 555 Array.init n_padded (fun i -> 530 556 if i < n then read_sample data (i * bps_bytes) bps else 0) 531 557 in 532 - (* Compute prediction residuals *) 533 558 let residuals = compute_residuals cfg samples in 534 - (* Estimate output size *) 535 559 let est = max 64 (Bytes.length data * 2) in 536 560 let bw = Bitwriter.create est in 537 - (* CCSDS format: no header. Encode blocks in RSI segments. *) 538 561 let id_len = id_len_of_bps bps in 539 562 let blocks_per_rsi = cfg.rsi in 540 563 let total_blocks = n_padded / j in 541 564 let block_idx = ref 0 in 542 565 while !block_idx < total_blocks do 543 - (* Start of an RSI *) 544 566 let b = ref 0 in 545 567 while !b < blocks_per_rsi && !block_idx + !b < total_blocks do 546 - let global_block = !block_idx + !b in 547 - let ofs = global_block * j in 548 - let is_ref = !b = 0 in 549 - let ref_sample = if is_ref then samples.(ofs) else 0 in 550 - if is_zero_block residuals ofs j is_ref then begin 551 - (* Count consecutive zero blocks for aggregation *) 552 - let run = ref 1 in 553 - while 554 - !b + !run < blocks_per_rsi 555 - && !block_idx + !b + !run < total_blocks 556 - && is_zero_block residuals ((!block_idx + !b + !run) * j) j false 557 - do 558 - incr run 559 - done; 560 - let blocks_remaining = 561 - min blocks_per_rsi (total_blocks - !block_idx) - !b 562 - in 563 - encode_zero_blocks bw bps id_len is_ref ref_sample !run 564 - blocks_remaining; 565 - b := !b + !run 566 - end 567 - else begin 568 - encode_ccsds_block bw residuals ofs j bps id_len is_ref ref_sample; 569 - incr b 570 - end 568 + let consumed = 569 + encode_one_block bw residuals samples j bps id_len blocks_per_rsi 570 + total_blocks !block_idx !b 571 + in 572 + b := !b + consumed 571 573 done; 572 574 block_idx := !block_idx + blocks_per_rsi 573 575 done; 574 576 Bitwriter.to_bytes bw 577 + 578 + (* -- Decompress ----------------------------------------------------------- *) 579 + 580 + let decode_rsi br block_pos b j bps id_len blocks_per_rsi total_blocks 581 + all_residuals = 582 + let is_ref = !b = 0 in 583 + if Bitreader.bits_remaining br < id_len + 1 then begin 584 + block_pos := total_blocks; 585 + 1 575 586 end 587 + else 588 + let out_pos = !block_pos * j in 589 + let blocks_remaining = 590 + min (blocks_per_rsi - !b) (total_blocks - !block_pos) 591 + in 592 + decode_ccsds_blocks br j bps id_len is_ref all_residuals out_pos 593 + blocks_remaining 576 594 577 - (* -- Decompress ----------------------------------------------------------- *) 595 + let decompress_blocks br cfg n_padded = 596 + let bps = cfg.bits_per_sample in 597 + let id_len = id_len_of_bps bps in 598 + let j = cfg.block_size in 599 + let blocks_per_rsi = cfg.rsi in 600 + let all_residuals = Array.make n_padded 0 in 601 + let block_pos = ref 0 in 602 + let total_blocks = n_padded / j in 603 + while !block_pos < total_blocks do 604 + let rsi_start = !block_pos in 605 + let b = ref 0 in 606 + while !b < blocks_per_rsi && !block_pos < total_blocks do 607 + let consumed = 608 + decode_rsi br block_pos b j bps id_len blocks_per_rsi total_blocks 609 + all_residuals 610 + in 611 + block_pos := !block_pos + consumed; 612 + b := !b + consumed 613 + done; 614 + if !block_pos < rsi_start + blocks_per_rsi && !block_pos < total_blocks then 615 + block_pos := min total_blocks (rsi_start + blocks_per_rsi) 616 + done; 617 + all_residuals 578 618 579 619 let decompress ~sample_count cfg data = 580 620 if Bytes.length data = 0 || sample_count = 0 then Ok Bytes.empty ··· 583 623 let bps = cfg.bits_per_sample in 584 624 let bps_bytes = bytes_per_sample bps in 585 625 let br = Bitreader.create data in 586 - let id_len = id_len_of_bps bps in 587 626 let j = cfg.block_size in 588 - let blocks_per_rsi = cfg.rsi in 589 - (* Pad to full blocks for decoding *) 590 627 let n_padded = (sample_count + j - 1) / j * j in 591 - let all_residuals = Array.make n_padded 0 in 592 - let block_pos = ref 0 in 593 - (* current block index *) 594 - let total_blocks = n_padded / j in 595 - while !block_pos < total_blocks do 596 - (* Decode one RSI *) 597 - let rsi_start = !block_pos in 598 - let b = ref 0 in 599 - while !b < blocks_per_rsi && !block_pos < total_blocks do 600 - let is_ref = !b = 0 in 601 - if Bitreader.bits_remaining br < id_len + 1 then 602 - (* Not enough bits; fill remaining with zeros *) 603 - block_pos := total_blocks 604 - else begin 605 - let out_pos = !block_pos * j in 606 - let blocks_remaining = blocks_per_rsi - !b in 607 - let blocks_remaining = 608 - min blocks_remaining (total_blocks - !block_pos) 609 - in 610 - let consumed = 611 - decode_ccsds_blocks br j bps id_len is_ref all_residuals out_pos 612 - blocks_remaining 613 - in 614 - block_pos := !block_pos + consumed; 615 - b := !b + consumed 616 - end 617 - done; 618 - (* If RSI was not fully consumed, advance to next RSI boundary *) 619 - if !block_pos < rsi_start + blocks_per_rsi && !block_pos < total_blocks 620 - then block_pos := min total_blocks (rsi_start + blocks_per_rsi) 621 - done; 622 - (* Truncate to requested sample count *) 628 + let all_residuals = decompress_blocks br cfg n_padded in 623 629 let residuals = Array.sub all_residuals 0 sample_count in 624 - (* Reconstruct samples from residuals *) 625 630 let samples = reconstruct_samples cfg residuals in 626 - (* Pack samples into output bytes *) 627 631 let out = Bytes.make (sample_count * bps_bytes) '\000' in 628 632 Array.iteri (fun i s -> write_sample out (i * bps_bytes) bps s) samples; 629 633 Ok out
+2 -1
test/dune
··· 1 1 (test 2 - (name test_rice) 2 + (name test) 3 + (modules test test_rice) 3 4 (libraries rice alcotest))
+1
test/test.ml
··· 1 + let () = Alcotest.run "rice" [ Test_rice.suite ]
+26 -35
test/test_rice.ml
··· 321 321 let result2 = roundtrip ~bps:8 cfg data2 in 322 322 Alcotest.(check bytes_eq) "block+1 roundtrip" data2 result2 323 323 324 - (* -- Runner --------------------------------------------------------------- *) 324 + (* -- Suite ---------------------------------------------------------------- *) 325 325 326 - let () = 327 - Alcotest.run "ccsds-121" 326 + let suite = 327 + ( "rice", 328 328 [ 329 - ( "roundtrip", 330 - [ 331 - Alcotest.test_case "random data" `Quick test_roundtrip_random; 332 - Alcotest.test_case "all zeros" `Quick test_all_zeros; 333 - Alcotest.test_case "all same value" `Quick test_all_same; 334 - Alcotest.test_case "ramp" `Quick test_ramp; 335 - Alcotest.test_case "random noise" `Quick test_random_noise; 336 - Alcotest.test_case "block sizes" `Quick test_block_sizes; 337 - Alcotest.test_case "bit depths" `Quick test_bit_depths; 338 - Alcotest.test_case "known vector" `Quick test_known_vector; 339 - Alcotest.test_case "empty input" `Quick test_empty; 340 - Alcotest.test_case "single sample" `Quick test_single_sample; 341 - Alcotest.test_case "predictors" `Quick test_predictors; 342 - ] ); 343 - ( "wire-format", 344 - [ 345 - Alcotest.test_case "ramp 0..7" `Quick test_wire_format_ramp; 346 - Alcotest.test_case "single 42" `Quick test_wire_format_single_42; 347 - Alcotest.test_case "single 255" `Quick test_wire_format_single_255; 348 - Alcotest.test_case "alternating 0/255" `Quick 349 - test_wire_format_alternating; 350 - Alcotest.test_case "all max" `Quick test_wire_format_all_max; 351 - ] ); 352 - ( "edge-cases", 353 - [ 354 - Alcotest.test_case "single sample all bps" `Quick 355 - test_single_sample_all_bps; 356 - Alcotest.test_case "max value block" `Quick test_max_value_block; 357 - Alcotest.test_case "alternating 0/max" `Quick test_alternating_0_max; 358 - Alcotest.test_case "partial block" `Quick test_partial_block; 359 - ] ); 360 - ] 329 + Alcotest.test_case "roundtrip random data" `Quick test_roundtrip_random; 330 + Alcotest.test_case "roundtrip all zeros" `Quick test_all_zeros; 331 + Alcotest.test_case "roundtrip all same value" `Quick test_all_same; 332 + Alcotest.test_case "roundtrip ramp" `Quick test_ramp; 333 + Alcotest.test_case "roundtrip random noise" `Quick test_random_noise; 334 + Alcotest.test_case "roundtrip block sizes" `Quick test_block_sizes; 335 + Alcotest.test_case "roundtrip bit depths" `Quick test_bit_depths; 336 + Alcotest.test_case "roundtrip known vector" `Quick test_known_vector; 337 + Alcotest.test_case "roundtrip empty input" `Quick test_empty; 338 + Alcotest.test_case "roundtrip single sample" `Quick test_single_sample; 339 + Alcotest.test_case "roundtrip predictors" `Quick test_predictors; 340 + Alcotest.test_case "wire ramp 0..7" `Quick test_wire_format_ramp; 341 + Alcotest.test_case "wire single 42" `Quick test_wire_format_single_42; 342 + Alcotest.test_case "wire single 255" `Quick test_wire_format_single_255; 343 + Alcotest.test_case "wire alternating 0/255" `Quick 344 + test_wire_format_alternating; 345 + Alcotest.test_case "wire all max" `Quick test_wire_format_all_max; 346 + Alcotest.test_case "edge single sample all bps" `Quick 347 + test_single_sample_all_bps; 348 + Alcotest.test_case "edge max value block" `Quick test_max_value_block; 349 + Alcotest.test_case "edge alternating 0/max" `Quick test_alternating_0_max; 350 + Alcotest.test_case "edge partial block" `Quick test_partial_block; 351 + ] )
+4
test/test_rice.mli
··· 1 + (** Test suite for [Rice]. *) 2 + 3 + val suite : string * unit Alcotest.test_case list 4 + (** [suite] is the alcotest suite for the [Rice] library. *)