unique-elements.scm 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. ; -*- mode: scheme; coding: utf-8 -*-
  2. ; Dependency sandbox, actually
  3. #|
  4. Pugh1992
  5. Eigenmann2017
  6. https://github.com/numpy/numpy/blob/main/numpy/core/src/common/mem_overlap.c
  7. https://github.com/Kraks/omega/blob/master/src/main/scala/omega/Omega.scala
  8. |#
  9. (import (only (srfi srfi-43) vector-copy! vector-fill! vector-every vector-any)
  10. (only (rnrs base) vector-map vector-for-each)
  11. (ice-9 control)
  12. (srfi srfi-26)
  13. (newra))
  14. (define (ra-unique-elements-brute-force? ra)
  15. (ra-fill! ra 0)
  16. (let/ec exit
  17. (ra-slice-for-each-in-order (ra-rank ra)
  18. (lambda (x)
  19. (if (zero? (x))
  20. (set! (x) 1)
  21. (exit #f)))
  22. ra)
  23. #t))
  24. (define (ra-unique-elements? ra)
  25. "
  26. Return @code{#t} if every combination of valid indices for the array @var{ra} yields a
  27. different element in @var{ra}'s root, otherwise return @code{#f}.
  28. "
  29. (let* ((dims (%%ra-dims ra)))
  30. (case (vector-length dims)
  31. ((0) #t)
  32. ((1) (let* ((dim (vector-ref dims 0))
  33. (len (dim-len dim)))
  34. (not (and (zero? (dim-step dim)) (or (not len) (> len 1))))))
  35. (else
  36. (let/ec return
  37. ; cheap cases
  38. (let ((sdims (sort dims (lambda (d0 d1) (< (magnitude (dim-step d0)) (magnitude (dim-step d1)))))))
  39. (let loop ((i 0) (c 1) (jump-over? #t))
  40. (if (< i (vector-length dims))
  41. (let* ((dim (vector-ref dims i))
  42. (len (dim-len dim)))
  43. ; len = 0
  44. (cond ((and=> len zero?)
  45. (return #t))
  46. ; step =0, len >1
  47. ((and (zero? (dim-step dim)) (or (not len) (> len 1)))
  48. (return #f))
  49. (else
  50. (loop (+ i 1)
  51. (* c len)
  52. ; must hold for every two consecutive axes
  53. (and jump-over?
  54. (or (>= (+ i 1) (vector-length dims))
  55. (let ((step (magnitude (dim-step (vector-ref sdims (+ i 1)))))
  56. (bdim (vector-ref sdims i)))
  57. (> step
  58. (* (magnitude (dim-step bdim))
  59. (max (magnitude (dim-hi bdim))
  60. (magnitude (dim-lo bdim))))))))))))
  61. ; size <=1
  62. (cond ((<= c 1) (return #t))
  63. ; long step axes jump over short step axes
  64. (jump-over? (return #t))
  65. ; expensive case
  66. (else
  67. ; we have to solve
  68. (throw 'not-yet)))))))))))
  69. (import (srfi 64))
  70. (test-begin "unique")
  71. (test-begin "cheap cases")
  72. (test-assert (ra-unique-elements? (ra-transpose (ra-copy (ra-i 4 5)) 0 0)))
  73. (test-assert (ra-unique-elements? (ra-transpose (ra-copy (ra-i 3 4 5)) 2 1 0)))
  74. (test-assert (ra-unique-elements? (ra-copy (ra-i 3 4 5))))
  75. (test-assert (not (ra-unique-elements? (ra-tile (ra-copy (ra-i 3 4 5)) 0 2))))
  76. (test-assert (ra-unique-elements? (ra-tile (ra-copy (ra-i 3 4 5)) 0 1)))
  77. (test-assert (ra-unique-elements? (ra-from (ra-tile (ra-copy (ra-i 3 4)) 0 2) (make-ra 0) (make-ra 1) (make-ra 2))))
  78. (test-assert (ra-unique-elements? (make-ra 0 '(1 3) '(-9 20))))
  79. (test-assert (ra-unique-elements? (ra-reverse (make-ra 0 '(1 3) '(-9 20)) 0)))
  80. (test-assert (ra-unique-elements? (ra-reverse (make-ra 0 '(1 3) '(-9 20)) 1)))
  81. (test-assert (ra-unique-elements? (ra-reverse (make-ra 0 '(1 3) '(-9 20)) 0 1)))
  82. (test-assert
  83. (catch 'not-yet
  84. (lambda ()
  85. (ra-unique-elements? (make-ra-root (ra-root (ra-copy #t (ra-i 10))) (vector (make-dim 3 3 2) (make-dim 3 3 1))))
  86. #f)
  87. (const #t)))
  88. (test-end "cheap cases")
  89. (test-end "unique")