matrix zero runs


Write a function that accepts an integer matrix and returns a copy of the matrix in which each the zero value in the original matrix has been smeared along the row and column containing it in the copy.

 $ cat mzr.rkt 
 #lang racket 
  
 (require math/matrix) 
    
 (define (matrix-zero-runs m) 
  
   ; Return a copy of the given integer matrix m.  The copy has a  
   ; zero row and column intersecting at the location of every  
   ; zero element in m. 
  
   ; This code is disgusting. 
  
   (define (zero-row-info) 
  
     ; Return 
     ; 
     ; a list of boolean zero-row indicators.  The ith element in the 
     ; list is #t iff the ith row contains a zero element. 
     ; 
     ; a row vector in which each element is either zero iff at least 
     ; one column in m contains a corresponding zero element or one 
     ; otherwise (that is, iff every column in m has a corresponding 
     ; non-zero element). 
  
     (let* 
          
       ((zri (make-vector (matrix-num-rows m) #f)) 
        (zri-check 
          (lambda (ri e) 
            (vector-set! zri ri (or (= e 0) (vector-ref zri ri)))))) 
        
       (let loop 
          
         ((r (- (matrix-num-rows m) 1)) 
          (rzm (make-matrix 1 (matrix-num-cols m) 1))) 
        
         (if (< r 0) 
           (values (vector->list zri) rzm) 
           (loop (- r 1) 
                 (matrix-map 
                  (lambda (e1 e2) 
                    (zri-check r e1) (if (or (= e1 0) (= e2 0)) 0 1)) 
                  (matrix-row m r) rzm)))))) 
  
     (let-values (((zero-row-indices zero-col-mask) (zero-row-info))) 
       (let ((zero-row (make-matrix 1 (matrix-num-cols m) 0))) 
         (matrix-map-rows 
          (lambda (row) 
            (let ((zr (car zero-row-indices))) 
              (set! zero-row-indices (cdr zero-row-indices)) 
              (if zr 
                zero-row 
                (matrix-map * row zero-col-mask)))) 
          m)))) 
  
  
 (require rackunit) 
  
 (check-equal? (matrix-zero-runs (matrix [[0]])) (matrix [[0]])) 
 (check-equal? (matrix-zero-runs (matrix [[1]])) (matrix [[1]])) 
 (check-equal? (matrix-zero-runs (matrix [[1 0][0 1]])) (make-matrix 2 2 0)) 
 (check-equal? (matrix-zero-runs (matrix [[0 1][1 0]])) (make-matrix 2 2 0)) 
 (check-equal? 
   (matrix-zero-runs (matrix [[0 1][1 1]])) (matrix [[0 0][0 1]])) 
 (check-equal? 
   (matrix-zero-runs (matrix [[1 0][1 1]])) (matrix [[0 0][1 0]])) 
 (check-equal? 
   (matrix-zero-runs (matrix [[1 1][0 1]])) (matrix [[0 1][0 0]])) 
 (check-equal? 
   (matrix-zero-runs (matrix [[1 1][1 0]])) (matrix [[1 0][0 0]])) 
  
 $ mzscheme mzr.rkt 
  
 $