Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
TAO
tao-rt
Commits
834a6e42
Commit
834a6e42
authored
Mar 08, 2022
by
Éric Thiébaut
Browse files
Generalize layouts to non-mirror things
parent
b812d324
Changes
8
Hide whitespace changes
Inline
Side-by-side
alpao/alpao-core.c
View file @
834a6e42
...
...
@@ -11,6 +11,7 @@
#include
"tao-alpao.h"
#include
"tao-errors.h"
#include
"tao-layouts.h"
#include
"tao-generic.h"
#include
<asdkWrapper.h>
...
...
@@ -194,7 +195,7 @@ uint8_t* alpao_mirror_mask_create_by_name(
dims
[
0
]
=
dim
;
dims
[
1
]
=
dim
;
}
return
tao_
mirror
_mask_create
(
dim
,
dim
,
nacts
);
return
tao_
layout
_mask_create
(
dim
,
dim
,
nacts
);
}
}
}
...
...
@@ -226,7 +227,7 @@ uint8_t* alpao_mirror_mask_create_by_nacts(
dims
[
0
]
=
dim
;
dims
[
1
]
=
dim
;
}
return
tao_
mirror
_mask_create
(
dim
,
dim
,
nacts
);
return
tao_
layout
_mask_create
(
dim
,
dim
,
nacts
);
}
// OPERATIONS ON MIRROR INSTANCES ---------------------------------------------
...
...
alpao/alpao-server.c
View file @
834a6e42
...
...
@@ -10,6 +10,7 @@
// Copyright (C) 2021-2022, Éric Thiébaut.
#include
"tao-alpao.h"
#include
"tao-layouts.h"
#include
"tao-errors.h"
#include
"tao-generic.h"
#include
"tao-remote-mirrors-private.h"
...
...
base/Makefile.am
View file @
834a6e42
...
...
@@ -56,6 +56,7 @@ include_HEADERS = \
tao-errors.h
\
tao-fits.h
\
tao-generic.h
\
tao-layouts.h
\
tao-macros.h
\
tao-options.h
\
tao-pixels.h
\
...
...
@@ -87,6 +88,7 @@ libtao_la_SOURCES = \
copy.c
\
encodings.c
\
errors.c
\
layouts.c
\
logmsg.c
\
options.c
\
pixels.c
\
...
...
base/layouts.c
0 → 100644
View file @
834a6e42
// tao-layouts.c -
//
// Implementation of 2-dimensional layouts of active elements in TAO.
//
//-----------------------------------------------------------------------------
//
// This file if part of TAO real-time software licensed under the MIT license
// (https://git-cral.univ-lyon1.fr/tao/tao-rt).
//
// Copyright (C) 2022, Éric Thiébaut.
#include
<string.h>
#include
"tao-utils.h"
#include
"tao-layouts.h"
#include
"tao-errors.h"
#include
"tao-generic.h"
// Macros to access 2-D arrays in column-major order.
#define MSK(i1,i2) msk[(i1) + dim1*(i2)]
#define INDS(j1,j2) inds[(j1) + dim1*(j2)]
long
tao_indexed_layout_build
(
long
*
inds
,
const
uint8_t
*
msk
,
long
dim1
,
long
dim2
,
unsigned
int
orient
)
{
long
k
=
0
;
if
(
msk
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
-
1L
;
}
if
(
dim1
<
1
||
dim2
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
-
1L
;
}
if
(
inds
==
NULL
)
{
// Just count the number of active sites.
long
ntot
=
dim1
*
dim2
;
for
(
long
i
=
0
;
i
<
ntot
;
++
i
)
{
if
(
msk
[
i
]
!=
0
)
{
++
k
;
}
}
}
else
{
// What is the direction of the numbering?
bool
reverse_1
=
(
orient
&
1
)
!=
0
;
bool
reverse_2
=
(
orient
&
2
)
!=
0
;
bool
swap_axes
=
(
orient
&
4
)
!=
0
;
// Fill array of indices according to direction of numbering.
if
(
swap_axes
)
{
// Numbering is in row-major order.
for
(
long
i1
=
0
;
i1
<
dim1
;
++
i1
)
{
long
j1
=
(
reverse_1
?
(
dim1
-
1
)
-
i1
:
i1
);
for
(
long
i2
=
0
;
i2
<
dim2
;
++
i2
)
{
long
j2
=
(
reverse_2
?
(
dim2
-
1
)
-
i2
:
i2
);
if
(
MSK
(
i1
,
i2
)
!=
0
)
{
INDS
(
j1
,
j2
)
=
k
;
++
k
;
}
else
{
INDS
(
j1
,
j2
)
=
-
1
;
}
}
}
}
else
{
// Numbering is in column-major order.
for
(
long
i2
=
0
;
i2
<
dim2
;
++
i2
)
{
long
j2
=
(
reverse_2
?
(
dim2
-
1
)
-
i2
:
i2
);
for
(
long
i1
=
0
;
i1
<
dim1
;
++
i1
)
{
long
j1
=
(
reverse_1
?
(
dim1
-
1
)
-
i1
:
i1
);
if
(
MSK
(
i1
,
i2
)
!=
0
)
{
INDS
(
j1
,
j2
)
=
k
;
++
k
;
}
else
{
INDS
(
j1
,
j2
)
=
-
1
;
}
}
}
}
}
return
k
;
}
#undef MSK
#undef INDS
long
tao_indexed_layout_check
(
const
long
*
inds
,
long
dim1
,
long
dim2
)
{
if
(
inds
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
-
1
;
}
if
(
dim1
<
1
||
dim2
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
-
1
;
}
long
length
=
dim1
*
dim2
;
long
count
=
0
;
for
(
long
i
=
0
;
i
<
length
;
++
i
)
{
if
(
inds
[
i
]
>=
0
)
{
++
count
;
}
}
for
(
long
i
=
0
;
i
<
length
;
++
i
)
{
if
(
inds
[
i
]
>=
count
)
{
tao_store_error
(
__func__
,
TAO_OUT_OF_RANGE
);
return
-
1
;
}
}
return
count
;
}
uint8_t
*
tao_layout_mask_create_from_text
(
char
const
*
shape
[],
long
nrows
,
long
dims
[
2
])
{
// Check arguments.
if
(
shape
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
NULL
;
}
if
(
nrows
==
-
1
)
{
// Count number of rows.
nrows
=
0
;
while
(
shape
[
nrows
]
!=
NULL
)
{
++
nrows
;
}
}
if
(
nrows
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
// Count number of columns.
long
ncols
=
0
;
for
(
long
i
=
0
;
i
<
nrows
;
++
i
)
{
long
n
=
(
shape
[
i
]
==
NULL
)
?
0
:
strlen
(
shape
[
i
]);
if
(
i
==
0
)
{
ncols
=
n
;
}
else
if
(
n
!=
ncols
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
}
if
(
ncols
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
// Convert the shape into a mask (the shape is in row-major storage order,
// the mask is in column-major storage order).
uint8_t
*
msk
=
tao_malloc
(
ncols
*
nrows
*
sizeof
(
uint8_t
));
if
(
msk
==
NULL
)
{
return
NULL
;
}
for
(
long
i
=
0
;
i
<
nrows
;
++
i
)
{
const
char
*
row
=
shape
[
i
];
for
(
long
j
=
0
;
j
<
ncols
;
++
j
)
{
msk
[
i
*
ncols
+
j
]
=
(
row
[
j
]
==
' '
?
0
:
1
);
}
}
// Return results.
if
(
dims
!=
NULL
)
{
dims
[
0
]
=
ncols
;
dims
[
1
]
=
nrows
;
}
return
msk
;
}
uint8_t
*
tao_layout_mask_create
(
long
dim1
,
long
dim2
,
long
nacts
)
{
if
(
dim1
<
1
||
dim2
<
1
||
nacts
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
long
len
=
dim1
*
dim2
;
uint8_t
*
mask
=
tao_malloc
(
len
*
sizeof
(
uint8_t
));
if
(
mask
==
NULL
)
{
return
NULL
;
}
return
tao_layout_mask_instanciate
(
mask
,
dim1
,
dim2
,
nacts
,
NULL
);
}
uint8_t
*
tao_layout_mask_instanciate
(
uint8_t
*
mask
,
long
dim1
,
long
dim2
,
long
nacts
,
long
*
work
)
{
if
(
dim1
<
1
||
dim2
<
1
||
nacts
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
if
(
mask
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
NULL
;
}
long
len
=
dim1
*
dim2
;
if
(
nacts
>
len
)
{
for
(
long
i
=
0
;
i
<
len
;
++
i
)
{
mask
[
i
]
=
true
;
}
return
mask
;
}
bool
own_work
=
(
work
==
NULL
);
if
(
own_work
)
{
// Allocate workspace.
work
=
tao_malloc
(
len
*
sizeof
(
long
));
if
(
work
==
NULL
)
{
return
NULL
;
}
}
// Instantiate workspace with f(i1,i2) and compute its extreme values.
long
q1
=
dim1
-
1
;
long
q2
=
dim2
-
1
;
for
(
long
i2
=
0
;
i2
<
dim2
;
++
i2
)
{
long
f2
=
(
q2
-
i2
)
*
i2
;
for
(
long
i1
=
0
;
i1
<
dim1
;
++
i1
)
{
long
f1
=
(
q1
-
i1
)
*
i1
;
work
[
i1
+
dim1
*
i2
]
=
f1
+
f2
;
}
}
long
fmin
=
work
[
0
],
fmax
=
work
[
0
];
for
(
long
i
=
1
;
i
<
len
;
++
i
)
{
long
f
=
work
[
i
];
fmin
=
tao_min
(
fmin
,
f
);
fmax
=
tao_max
(
fmax
,
f
);
}
// Build the tightest bracket t1 ≥ t2 such that n1 ≤ nacts ≤ n2, with
// n1 = count(msk ≥ t1) and similarly for n2 and t2.
long
t1
=
fmin
,
n1
=
len
;
long
t2
=
fmin
,
n2
=
len
;
while
(
n1
>
nacts
)
{
t2
=
t1
;
n2
=
n1
;
t1
=
fmax
;
n1
=
0
;
for
(
long
i
=
0
;
i
<
len
;
++
i
)
{
long
f
=
work
[
i
];
if
((
t2
<
f
)
&
(
f
<
t1
))
{
// Strictly between the disks defined by t1 and t2.
t1
=
f
;
}
n1
+=
(
f
>=
t1
);
}
}
long
t
=
(
nacts
-
n1
<
n2
-
nacts
?
t1
:
t2
);
long
n
=
(
t
==
t1
?
n1
:
n2
);
if
(
n
!=
nacts
)
{
fprintf
(
stderr
,
"WARNING: Only found an approximation with %ld "
"active elements instead of %ld.
\n
"
,
n
,
nacts
);
}
for
(
long
i
=
0
;
i
<
len
;
++
i
)
{
mask
[
i
]
=
(
work
[
i
]
>=
t
);
}
if
(
own_work
)
{
tao_free
(
work
);
}
return
mask
;
}
base/remote-mirrors.c
View file @
834a6e42
...
...
@@ -647,229 +647,3 @@ tao_status tao_remote_mirror_run_loop(
}
return
status
;
}
//-----------------------------------------------------------------------------
// UTILITIES
// Macros to access 2-D arrays in column-major order.
#define MSK(i1,i2) msk[(i1) + dim1*(i2)]
#define INDS(j1,j2) inds[(j1) + dim1*(j2)]
long
tao_indexed_layout_build
(
long
*
inds
,
const
uint8_t
*
msk
,
long
dim1
,
long
dim2
,
unsigned
int
orient
)
{
long
k
=
0
;
if
(
msk
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
-
1L
;
}
if
(
dim1
<
1
||
dim2
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
-
1L
;
}
if
(
inds
==
NULL
)
{
// Just count the number of active sites.
long
ntot
=
dim1
*
dim2
;
for
(
long
i
=
0
;
i
<
ntot
;
++
i
)
{
if
(
msk
[
i
]
!=
0
)
{
++
k
;
}
}
}
else
{
// What is the direction of the numbering?
bool
reverse_1
=
(
orient
&
1
)
!=
0
;
bool
reverse_2
=
(
orient
&
2
)
!=
0
;
bool
swap_axes
=
(
orient
&
4
)
!=
0
;
// Fill array of indices according to direction of numbering.
if
(
swap_axes
)
{
// Numbering is in row-major order.
for
(
long
i1
=
0
;
i1
<
dim1
;
++
i1
)
{
long
j1
=
(
reverse_1
?
(
dim1
-
1
)
-
i1
:
i1
);
for
(
long
i2
=
0
;
i2
<
dim2
;
++
i2
)
{
long
j2
=
(
reverse_2
?
(
dim2
-
1
)
-
i2
:
i2
);
if
(
MSK
(
i1
,
i2
)
!=
0
)
{
INDS
(
j1
,
j2
)
=
k
;
++
k
;
}
else
{
INDS
(
j1
,
j2
)
=
-
1
;
}
}
}
}
else
{
// Numbering is in column-major order.
for
(
long
i2
=
0
;
i2
<
dim2
;
++
i2
)
{
long
j2
=
(
reverse_2
?
(
dim2
-
1
)
-
i2
:
i2
);
for
(
long
i1
=
0
;
i1
<
dim1
;
++
i1
)
{
long
j1
=
(
reverse_1
?
(
dim1
-
1
)
-
i1
:
i1
);
if
(
MSK
(
i1
,
i2
)
!=
0
)
{
INDS
(
j1
,
j2
)
=
k
;
++
k
;
}
else
{
INDS
(
j1
,
j2
)
=
-
1
;
}
}
}
}
}
return
k
;
}
#undef MSK
#undef INDS
uint8_t
*
tao_mirror_mask_create
(
long
dim1
,
long
dim2
,
long
nacts
)
{
if
(
dim1
<
1
||
dim2
<
1
||
nacts
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
long
len
=
dim1
*
dim2
;
uint8_t
*
mask
=
tao_malloc
(
len
*
sizeof
(
uint8_t
));
if
(
mask
==
NULL
)
{
return
NULL
;
}
return
tao_mirror_mask_instanciate
(
mask
,
dim1
,
dim2
,
nacts
,
NULL
);
}
uint8_t
*
tao_mirror_mask_instanciate
(
uint8_t
*
mask
,
long
dim1
,
long
dim2
,
long
nacts
,
long
*
work
)
{
if
(
dim1
<
1
||
dim2
<
1
||
nacts
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
if
(
mask
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
NULL
;
}
long
len
=
dim1
*
dim2
;
if
(
nacts
>
len
)
{
for
(
long
i
=
0
;
i
<
len
;
++
i
)
{
mask
[
i
]
=
true
;
}
return
mask
;
}
bool
own_work
=
(
work
==
NULL
);
if
(
own_work
)
{
// Allocate workspace.
work
=
tao_malloc
(
len
*
sizeof
(
long
));
if
(
work
==
NULL
)
{
return
NULL
;
}
}
// Instantiate workspace with f(i1,i2) and compute its extreme values.
long
q1
=
dim1
-
1
;
long
q2
=
dim2
-
1
;
for
(
long
i2
=
0
;
i2
<
dim2
;
++
i2
)
{
long
f2
=
(
q2
-
i2
)
*
i2
;
for
(
long
i1
=
0
;
i1
<
dim1
;
++
i1
)
{
long
f1
=
(
q1
-
i1
)
*
i1
;
work
[
i1
+
dim1
*
i2
]
=
f1
+
f2
;
}
}
long
fmin
=
work
[
0
],
fmax
=
work
[
0
];
for
(
long
i
=
1
;
i
<
len
;
++
i
)
{
long
f
=
work
[
i
];
fmin
=
tao_min
(
fmin
,
f
);
fmax
=
tao_max
(
fmax
,
f
);
}
// Build the tightest bracket t1 ≥ t2 such that n1 ≤ nacts ≤ n2, with
// n1 = count(msk ≥ t1) and similarly for n2 and t2.
long
t1
=
fmin
,
n1
=
len
;
long
t2
=
fmin
,
n2
=
len
;
while
(
n1
>
nacts
)
{
t2
=
t1
;
n2
=
n1
;
t1
=
fmax
;
n1
=
0
;
for
(
long
i
=
0
;
i
<
len
;
++
i
)
{
long
f
=
work
[
i
];
if
((
t2
<
f
)
&
(
f
<
t1
))
{
// Strictly between the disks defined by t1 and t2.
t1
=
f
;
}
n1
+=
(
f
>=
t1
);
}
}
long
t
=
(
nacts
-
n1
<
n2
-
nacts
?
t1
:
t2
);
long
n
=
(
t
==
t1
?
n1
:
n2
);
if
(
n
!=
nacts
)
{
fprintf
(
stderr
,
"WARNING: Only found an approximation with %ld "
"actuators instead of %ld.
\n
"
,
n
,
nacts
);
}
for
(
long
i
=
0
;
i
<
len
;
++
i
)
{
mask
[
i
]
=
(
work
[
i
]
>=
t
);
}
if
(
own_work
)
{
tao_free
(
work
);
}
return
mask
;
}
uint8_t
*
tao_mirror_mask_create_from_text
(
char
const
*
shape
[],
long
nrows
,
long
dims
[
2
])
{
// Check arguments.
if
(
shape
==
NULL
)
{
tao_store_error
(
__func__
,
TAO_BAD_ADDRESS
);
return
NULL
;
}
if
(
nrows
<=
0
)
{
// Count number of rows.
nrows
=
0
;
while
(
shape
[
nrows
]
!=
NULL
)
{
++
nrows
;
}
}
// Count number of columns.
long
ncols
=
0
;
for
(
long
i
=
0
;
i
<
nrows
;
++
i
)
{
long
n
=
(
shape
[
i
]
==
NULL
)
?
0
:
strlen
(
shape
[
i
]);
if
(
i
==
0
)
{
ncols
=
n
;
}
else
if
(
n
!=
ncols
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
}
if
(
ncols
<
1
||
nrows
<
1
)
{
tao_store_error
(
__func__
,
TAO_BAD_SIZE
);
return
NULL
;
}
// Convert the shape into a mask (the shape is in row-major storage order,
// the mask is in column-major storage order).
uint8_t
*
msk
=
tao_malloc
(
ncols
*
nrows
*
sizeof
(
uint8_t
));
if
(
msk
==
NULL
)
{
return
NULL
;
}
for
(
long
i
=
0
;
i
<
nrows
;
++
i
)
{
const
char
*
row
=
shape
[
i
];
for
(
long
j
=
0
;
j
<
ncols
;
++
j
)
{
msk
[
i
*
ncols
+
j
]
=
(
row
[
j
]
==
' '
?
0
:
1
);
}
}
// Return results.
if
(
dims
!=
NULL
)
{
dims
[
0
]
=
ncols
;
dims
[
1
]
=
nrows
;
}
return
msk
;
}
base/tao-fake-mirror-server.c
View file @
834a6e42
...
...
@@ -10,6 +10,7 @@
// Copyright (C) 2021-2022, Éric Thiébaut.
#include
"tao-basics.h"
#include
"tao-layouts.h"
#include
"tao-remote-mirrors-private.h"
#include
"tao-generic.h"
#include
"tao-errors.h"
...
...
@@ -232,7 +233,7 @@ int main(
progname
);
return
EXIT_FAILURE
;
}
if
(
tao_
mirror
_mask_instanciate
(
msk
,
dim
,
dim
,
nacts
,
inds
)
==
NULL
)
{
if
(
tao_
layout
_mask_instanciate
(
msk
,
dim
,
dim
,
nacts
,
inds
)
==
NULL
)
{
fprintf
(
stderr
,
"%s: failed to instantiate mirror mask
\n
"
,
progname
);
return
EXIT_FAILURE
;
...
...
base/tao-layouts.h
0 → 100644
View file @
834a6e42
// tao-layouts.h -
//
// Definitions and API for 2-dimensional layouts of active nodes in TAO.
//
//-----------------------------------------------------------------------------
//
// This file if part of TAO real-time software licensed under the MIT license
// (https://git-cral.univ-lyon1.fr/tao/tao-rt).
//
// Copyright (C) 2022, Éric Thiébaut.
#ifndef TAO_LAYOUTS_H_
#define TAO_LAYOUTS_H_ 1
#include
<tao-basics.h>
TAO_BEGIN_DECLS
/**
* @addtogroup Laoyuts Two-dimensional layouts of active nodes.
*
* @ingroup Utilities
*
* @brief Common types and methods for 2-dimensional layouts of active nodes.
*
* @{
*/
/**
* Build an indexed layout given a mask.
*
* This function computes the number and the indices of active nodes in a 2-D
* array.
*
* The input mask `msk` is a `dim1` by `dim2` array of bytes where active nodes
* have a non-zero value.
*
* The destination array is a `dim1` by `dim2` array of integers where active
* nodes are set with their nonnegative indices while inactive nodes are set to
* `-1`. The active indices are unique and vary from `0` to `n - 1` with `n`
* the number of active nodes.
*
* The least significant bits of `orient` specify how to order the numbering of
* the active nodes:
*
* - If the 1st bit of `orient` is set, the numbering is decreasing along the
* 1st dimension; otherwise, the numbering is increasing along the 1st