Skip to content

Commit 1cc1526

Browse files
committed
add antidiagonal
1 parent 4139379 commit 1cc1526

File tree

1 file changed

+69
-58
lines changed

1 file changed

+69
-58
lines changed

source/mir/ndslice/topology.d

Lines changed: 69 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ Params:
668668
slice = input slice
669669
Returns:
670670
1-dimensional slice composed of diagonal elements
671+
See_also: $(LREF antidiagonal)
671672
+/
672673
Slice!(packs[0] == 1 ? kind : Universal, 1 ~ packs[1 .. $], Iterator)
673674
diagonal
@@ -758,20 +759,6 @@ version(mir_test) unittest
758759
assert(a.diagonal == d);
759760
}
760761

761-
/// Matrix, antidiagonal
762-
@safe @nogc pure nothrow version(mir_test) unittest
763-
{
764-
import mir.ndslice.dynamic : dropToHypercube, reversed;
765-
// -------
766-
// | 0 1 2 |
767-
// | 3 4 5 |
768-
// -------
769-
//->
770-
// | 1 3 |
771-
static immutable d = [1, 3];
772-
assert(iota(2, 3).universal.dropToHypercube.reversed!1.diagonal == d);
773-
}
774-
775762
/// 3D, main diagonal
776763
@safe @nogc pure nothrow version(mir_test) unittest
777764
{
@@ -844,6 +831,61 @@ version(mir_test) unittest
844831
assert(slice == d);
845832
}
846833

834+
/++
835+
Returns a 1-dimensional slice over the main antidiagonal of an 2D-dimensional slice.
836+
`antidiagonal` can be generalized with other selectors such as
837+
$(LREF blocks) (diagonal blocks) and $(LREF windows) (multi-diagonal slice).
838+
839+
It runs from the top right corner to the bottom left corner.
840+
841+
Pseudo_code:
842+
------
843+
auto antidiagonal = slice.dropToHypercube.reversed!1.diagonal;
844+
------
845+
846+
Params:
847+
slice = input slice
848+
Returns:
849+
1-dimensional slice composed of antidiagonal elements.
850+
See_also: $(LREF diagonal)
851+
+/
852+
Slice!(Universal, 1 ~ packs[1 .. $], Iterator)
853+
antidiagonal
854+
(SliceKind kind, size_t[] packs, Iterator)
855+
(Slice!(kind, packs, Iterator) slice)
856+
if (packs[0] == 2)
857+
{
858+
import mir.ndslice.dynamic : dropToHypercube, reversed;
859+
return slice.dropToHypercube.reversed!1.diagonal;
860+
}
861+
862+
///
863+
@safe @nogc pure nothrow version(mir_test) unittest
864+
{
865+
// -----
866+
// | 0 1 |
867+
// | 2 3 |
868+
// -----
869+
//->
870+
// | 1 2 |
871+
static immutable c = [1, 2];
872+
import std.stdio;
873+
assert(iota(2, 2).antidiagonal == c);
874+
}
875+
876+
///
877+
@safe @nogc pure nothrow version(mir_test) unittest
878+
{
879+
// -------
880+
// | 0 1 2 |
881+
// | 3 4 5 |
882+
// -------
883+
//->
884+
// | 1 3 |
885+
static immutable d = [1, 3];
886+
assert(iota(2, 3).antidiagonal == d);
887+
}
888+
847889
/++
848890
Returns an n-dimensional slice of n-dimensional non-overlapping blocks.
849891
`blocks` can be generalized with other selectors.
@@ -3076,53 +3118,22 @@ auto magic(size_t length)
30763118
@safe pure nothrow
30773119
version(mir_test) unittest
30783120
{
3079-
auto isMagic(S)(S matrix)
3121+
bool isMagic(S)(S matrix)
30803122
{
30813123
import mir.math.sum;
3082-
import mir.ndslice.algorithm: all;
3083-
import mir.ndslice.allocation: slice;
3084-
import mir.ndslice.dynamic: transposed, reversed;
3085-
import mir.ndslice.topology: flattened, universal, diagonal;
3086-
3087-
// check shape
3088-
if (matrix.length == 0)
3089-
return false;
3090-
if (matrix.length!0 != matrix.length!1)
3091-
return false;
3092-
3093-
// checks that matrix is composed of consequent elements from interval 1:N^2.
3094-
auto n2 = matrix.elementsCount;
3095-
enum bc = size_t.sizeof * 8;
3096-
auto flags = slice!size_t(n2 / bc + (n2 % bc != 0))
3097-
.bitwise[0 .. n2];
3098-
foreach(elem; matrix.flattened)
3099-
{
3100-
assert(elem > 0);
3101-
assert(elem <= n2);
3102-
flags[elem - 1] = true;
3103-
}
3104-
if (!flags.all)
3105-
return false;
3106-
3107-
// calculate magic number
3124+
import mir.ndslice: magic, byDim, map, repeat, diagonal, antidiagonal;
31083125
auto n = matrix.length;
3109-
auto c = n * (n * n + 1) / 2;
3110-
3111-
// each row sum should equal magic number
3112-
foreach(row; matrix)
3113-
if (row.sum != c)
3114-
return false;
3115-
// each columns sum should equal magic number
3116-
foreach(col; matrix.universal.transposed)
3117-
if (col.sum != c)
3118-
return false;
3119-
// each diagonal sum should equal magic number
3120-
if (matrix.diagonal.sum != c)
3121-
return false;
3122-
if (matrix.universal.reversed!0.diagonal.sum != c)
3123-
return false;
3124-
3125-
return true;
3126+
auto c = n * (n * n + 1) / 2; // magic number
3127+
return // check shape
3128+
matrix.length!0 > 0 && matrix.length!0 == matrix.length!1
3129+
&& // each row sum should equal magic number
3130+
matrix.byDim!0.map!sum == c.repeat(n)
3131+
&& // each columns sum should equal magic number
3132+
matrix.byDim!1.map!sum == c.repeat(n)
3133+
&& // diagonal sum should equal magic number
3134+
matrix.diagonal.sum == c
3135+
&& // antodiagonal sum should equal magic number
3136+
matrix.antidiagonal.sum == c;
31263137
}
31273138

31283139
assert(isMagic(magic(1)));

0 commit comments

Comments
 (0)