+/* --- @DA_SHRINK@ --- *
+ *
+ * Arguments: @a@ = pointer to array block (multiply evaluated)
+ * @n@ = number of slots to remove (multiply evaluated)
+ *
+ * Use: As for @DA_EXTEND@, with the sense of the argument reversed.
+ */
+
+#define DA_SHRINK(a, n) do { \
+ if ((n) > 0 && (n) > DA_LEN(a)) \
+ THROW(DAEXC_UFLOW); \
+ else if ((n) < 0 && -(n) > DA_SPARE(a)) \
+ THROW(DAEXC_OFLOW); \
+ DA_UNSAFE_SHRINK(a, n); \
+} while (0)
+
+/* --- @DA_UNSAFE_SHRINK@ --- *
+ *
+ * Arguments: @a@ = pointer to array block (multiply evaluated)
+ * @n@ = number of slots to add (multiply evaluated)
+ *
+ * Use: As for @DA_SHRINK@, only it doesn't check for errors.
+ */
+
+#define DA_UNSAFE_SHRINK(a, n) do { \
+ (a)->b.len -= (n); \
+} while (0)
+
+/* --- @DA_UNSLIDE@ --- *
+ *
+ * Arguments: @a@ = pointer to array block (multiply evaluated)
+ * @n@ = number of positions to slide the array (multiply
+ * evaluated)
+ *
+ *
+ * Use: As for @DA_SLIDE@, only in the other direction.
+ */
+
+#define DA_UNSLIDE(a, n) do { \
+ if ((n) > 0 && (n) > DA_LEN(a)) \
+ THROW(DAEXC_UFLOW); \
+ else if ((n) < 0 && -(n) > DA_OFFSET(a)) \
+ THROW(DAEXC_OFLOW); \
+ DA_UNSAFE_UNSLIDE((a), (n)); \
+} while (0)
+
+/* --- @DA_UNSAFE_UNSLIDE@ --- *
+ *
+ * Arguments: @a@ = pointer to array block (multiply evaluated)
+ * @n@ = number of positions to slide the array (multiply
+ * evaluated)
+ *
+ * Use: As for @DA_UNSLIDE@, only it doesn't check for errors.
+ */
+
+#define DA_UNSAFE_UNSLIDE(a, n) do { \
+ (a)->v += (n); \
+ (a)->b.len -= (n); \
+ (a)->b.sz -= (n); \
+ (a)->b.off += (n); \
+} while (0)
+