Repository: apytypes/apytypes (language: python)

Issue:
Issue with transposed NumPy arrays
As NumPy does transposition by changing the stride, the following calls gives the same resulting APyTypes array:

```
import numpy as np
from apytypes import APyFixedArray
a = np.asarray([[1, -1], [1, -1]])
a1 = APyFixedArray(a, 2, 3)
a2 = APyFixedArray(a.T, 2, 3)
assert a1.is_identical(a2)  # Should not be true
```

Solution is either to use strides in `APyTypes` (which is useful for fast transposition, but probably also other things...) and copy the stride of the input array, or take the stride into consideration when reading data from the NumPy array.


Discussion / hints:
Idea: keep our current internal representation and handle strides during load from other array-types.
```python3
from apytypes import *
import numpy as np

# 100 x 100 matrix
A = np.random.random((100, 100))
B = APyFixedArray.from_float(A, int_bits=2, frac_bits=14)

%timeit A * A
3.44 µs ± 16.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

%timeit A * A.T
9.79 µs ± 285 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

%timeit B * B
3.82 µs ± 14.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

%timeit B * B.T
27 µs ± 125 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)


AT = A.T
BT = B.T

%timeit A * AT
9.54 µs ± 58.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

%timeit B * BT
4.67 µs ± 92.7 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
```

Fix patch:
diff --git a/lib/apytypes/_apytypes.pyi b/lib/apytypes/_apytypes.pyi
index 1a3ed9ea7..ce7b0a9a5 100644
--- a/lib/apytypes/_apytypes.pyi
+++ b/lib/apytypes/_apytypes.pyi
@@ -40,12 +40,9 @@ class APyFixed:
         """
         Create an :class:`APyFixed` object from :class:`float`.
 
-        The initialized fixed-point value is the one closest to the
-        input floating-point value, rounded away from zero on ties. Exactly two of
-        the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) needs to be set.
-
-        Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-        to be set.
+        The initialized fixed-point value is the one closest to the input floating-point
+        value, rounded away from zero on ties. Exactly two of the three bit-specifiers
+        (`bits`, `int_bits`, `frac_bits`) must be set.
 
         Parameters
         ----------
@@ -80,8 +77,8 @@ class APyFixed:
         """
         Create an :class:`APyFixed` object from :class:`str`.
 
-        Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-        to be set.
+        Exactly two of three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be
+        set.
 
         Parameters
         ----------
@@ -201,8 +198,8 @@ class APyFixed:
         This is the primary method for performing quantization, truncation,
         overflowing, and saturation when dealing with APyTypes fixed-point numbers.
 
-        Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-        to be set.
+        Exactly two of three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be
+        set.
 
         Parameters
         ----------
@@ -247,7 +244,7 @@ class APyFixed:
 
         Two `APyFixed` objects are considered exactly identical if, and only if,
         they store the same fixed-point value, and have the exact same
-        bit-specification (*bits*, *int_bits*, and *frac_bits*). This is a more
+        bit-specification (`bits`, `int_bits`, and `frac_bits`). This is a more
         restrictive test than ``==``,  that only tests equality of the stored
         fixed-point value.
 
@@ -386,9 +383,9 @@ class APyFixedArray:
         """
         Create an :class:`APyFixedArray` object from a sequence of :class:`float`.
 
-        The initialized fixed-point values are the one closest to the
-        input floating-point value, rounded away from zero on ties. Exactly two of
-        the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) has to be set.
+        The initialized fixed-point values are the ones closest to the input
+        floating-point values, rounded away from zero on ties. Exactly two of the three
+        bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be set.
 
         Parameters
         ----------
@@ -427,6 +424,57 @@ class APyFixedArray:
             )
         """
 
+    @staticmethod
+    def from_array(
+        float_array,
+        int_bits: int | None = None,
+        frac_bits: int | None = None,
+        bits: int | None = None,
+    ) -> APyFixedArray:
+        """
+        Create an :class:`APyFixedArray` object from an ndarray.
+
+        The initialized fixed-point values are the ones closest to the input
+        floating-point values, rounded away from zero on ties. Exactly two of the three
+        bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be set.
+
+        Using ndarrays as input is generally faster than e.g. lists.
+
+        Parameters
+        ----------
+        float_sequence : sequence of float
+            Floating point values to initialize from. The tensor shape will be taken
+            from the sequence shape.
+        int_bits : int, optional
+            Number of integer bits in the created fixed-point tensor
+        frac_bits : int, optional
+            Number of fractional bits in the created fixed-point tensor
+        bits : int, optional
+            Total number of bits in the created fixed-point tensor
+
+        Returns
+        -------
+        :class:`APyFixedArray`
+
+        Examples
+        --------
+
+        .. code-block:: python
+
+            from apytypes import APyFixedArray
+            import numpy as np
+
+            # Array `a`, initialized from NumPy ndarray
+            a = APyFixedArray.from_array(
+                np.array([
+                    [1.0, 2.0, 3.0],
+                    [4.0, 5.0, 6.0],
+                ]),
+                int_bits=10,
+                frac_bits=0
+            )
+        """
+
     def __abs__(self) -> APyFixedArray: ...
     @typing.overload
     def __add__(self, arg0: APyFixedArray) -> APyFixedArray: ...
@@ -503,8 +551,8 @@ class APyFixedArray:
         This is the primary method for performing quantization, truncation, overflowing,
         and saturation when dealing with APyTypes fixed-point numbers.
 
-        Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-        to be set.
+        Exactly two of three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must
+        be set.
 
         Parameters
         ----------
@@ -661,7 +709,7 @@ class APyFloat:
             Floating-point value to initialize from.
         exp_bits : int
             Number of exponent bits.
-        man_bits : int, optional
+        man_bits : int
             Number of mantissa bits.
         bias : int, optional
             Bias.
@@ -923,8 +971,8 @@ class APyFloatArray:
     @staticmethod
     def from_float(
         float_sequence: typing.Sequence,
-        exp_bits: int = None,
-        man_bits: int = None,
+        exp_bits: int,
+        man_bits: int,
         bias: int | None = None,
         quantization: QuantizationMode | None = None,
     ) -> APyFloatArray:
@@ -938,7 +986,7 @@ class APyFloatArray:
             from the sequence shape.
         exp_bits : int
             Number of exponent bits in the created fixed-point tensor
-        man_bits : int, optional
+        man_bits : int
             Number of mantissa bits in the created fixed-point tensor
         bias : int, optional
             Bias in the created fixed-point tensor
@@ -971,6 +1019,55 @@ class APyFloatArray:
             )
         """
 
+    @staticmethod
+    def from_array(
+        float_sequence,
+        exp_bits: int,
+        man_bits: int,
+        bias: int | None = None,
+        quantization: QuantizationMode | None = None,
+    ) -> APyFloatArray:
+        """
+        Create an :class:`APyFloatArray` object from a sequence of :class:`float`.
+
+        Parameters
+        ----------
+        float_sequence : sequence of float
+            Floating point values to initialize from. The tensor shape will be taken
+            from the sequence shape.
+        exp_bits : int
+            Number of exponent bits in the created fixed-point tensor
+        man_bits : int
+            Number of mantissa bits in the created fixed-point tensor
+        bias : int, optional
+            Bias in the created fixed-point tensor
+        quantization : :class:`QuantizationMode`, optional
+            Quantization mode to use. If not provided, the global mode,
+            see :func:`get_float_quantization_mode`, is used.
+
+        Returns
+        -------
+        :class:`APyFloatArray`
+
+        Examples
+        --------
+
+        .. code-block:: python
+
+            from apytypes import APyFloatArray
+            import numpy as np
+
+            # Array `a`, initialized from NumPy ndarray
+            a = APyFloatArray.from_array(
+                np.array([
+                    [1.0, 2.0, 3.0],
+                    [4.0, 5.0, 6.0],
+                ]),
+                man_bits=10,
+                exp_bits=10
+            )
+        """
+
     @typing.overload
     def __add__(self, arg0: APyFloatArray) -> APyFloatArray: ...
     @typing.overload
diff --git a/src/apyfixed_wrapper.cc b/src/apyfixed_wrapper.cc
index 01948c724..84f5115fb 100644
--- a/src/apyfixed_wrapper.cc
+++ b/src/apyfixed_wrapper.cc
@@ -138,7 +138,7 @@ void bind_fixed(nb::module_& m)
 
             Two `APyFixed` objects are considered exactly identical if, and only if,
             they represent the same fixed-point value, and have the exact same
-            bit-specification (*bits*, *int_bits*, and *frac_bits*). This is a more
+            bit-specification (`bits`, `int_bits`, and `frac_bits`). This is a more
             restrictive test than ``==``,  that only tests equality of the numerical
             fixed-point value.
 
@@ -183,7 +183,7 @@ void bind_fixed(nb::module_& m)
             This is the primary method for performing quantization and
             overflowing/saturation when dealing with APyTypes fixed-point numbers.
 
-            Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
+            Exactly two of three bit-specifiers (`bits`, `int_bits`, `frac_bits`) needs
             to be set.
 
             Parameters
@@ -304,12 +304,9 @@ void bind_fixed(nb::module_& m)
             R"pbdoc(
             Create an :class:`APyFixed` object from :class:`float`.
 
-            The initialized fixed-point value is the one closest to the
-            input floating-point value, rounded away from zero on ties. Exactly two of
-            the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) needs to be set.
-
-            Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-            to be set.
+            The initialized fixed-point value is the one closest to the input
+            floating-point value, rounded away from zero on ties. Exactly two of the
+            three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be set.
 
             Parameters
             ----------
@@ -344,8 +341,8 @@ void bind_fixed(nb::module_& m)
             R"pbdoc(
             Create an :class:`APyFixed` object from :class:`str`.
 
-            Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-            to be set.
+            Exactly two of three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must
+            be set.
 
             Parameters
             ----------
diff --git a/src/apyfixedarray.cc b/src/apyfixedarray.cc
index 8d10d47b7..a4146909b 100644
--- a/src/apyfixedarray.cc
+++ b/src/apyfixedarray.cc
@@ -48,10 +48,10 @@ APyFixedArray::APyFixedArray(
           python_sequence_extract_shape(bit_pattern_sequence), int_bits, frac_bits, bits
       )
 {
-    // Specialized initialization for NumPy ndarrays
-    if (nb::isinstance<nb::ndarray<nb::numpy>>(bit_pattern_sequence)) {
-        auto ndarray = nb::cast<nb::ndarray<nb::numpy>>(bit_pattern_sequence);
-        _set_bits_from_numpy_ndarray(ndarray);
+    // Specialized initialization for NDArray
+    if (nb::isinstance<nb::ndarray<>>(bit_pattern_sequence)) {
+        auto ndarray = nb::cast<nb::ndarray<nb::c_contig>>(bit_pattern_sequence);
+        _set_bits_from_ndarray(ndarray);
         return; // initialization completed
     }
 
@@ -880,9 +880,9 @@ APyFixedArray APyFixedArray::from_double(
     std::optional<int> bits
 )
 {
-    if (nb::isinstance<nb::ndarray<nb::numpy>>(python_seq)) {
-        // Sequence is NumPy NDArray. Initialize using `from_array`
-        auto ndarray = nb::cast<nb::ndarray<>>(python_seq);
+    if (nb::isinstance<nb::ndarray<>>(python_seq)) {
+        // Sequence is NDArray. Initialize using `from_array`
+        auto ndarray = nb::cast<nb::ndarray<nb::c_contig>>(python_seq);
         return from_array(ndarray, int_bits, frac_bits, bits);
     }
 
@@ -926,7 +926,7 @@ APyFixedArray APyFixedArray::from_double(
 }
 
 APyFixedArray APyFixedArray::from_array(
-    const nb::ndarray<>& ndarray,
+    const nb::ndarray<nb::c_contig>& ndarray,
     std::optional<int> int_bits,
     std::optional<int> frac_bits,
     std::optional<int> bits
@@ -1415,7 +1415,7 @@ void APyFixedArray::_cast(
     }
 }
 
-void APyFixedArray::_set_bits_from_numpy_ndarray(const nb::ndarray<nb::numpy>& ndarray)
+void APyFixedArray::_set_bits_from_ndarray(const nb::ndarray<nb::c_contig>& ndarray)
 {
 #define CHECK_AND_SET_BITS_FROM_NPTYPE(__TYPE__)                                       \
     do {                                                                               \
@@ -1437,7 +1437,7 @@ void APyFixedArray::_set_bits_from_numpy_ndarray(const nb::ndarray<nb::numpy>& n
                     );                                                                 \
                 }                                                                      \
             }                                                                          \
-            return; /* Conversion completed, exit function */                          \
+            return; /* Conversion completed, exit `_set_bits_from_ndarray()` */        \
         }                                                                              \
     } while (0)
 
@@ -1459,12 +1459,12 @@ void APyFixedArray::_set_bits_from_numpy_ndarray(const nb::ndarray<nb::numpy>& n
     // of the `dtype`. Seems hard to achieve with nanobind, but please fix this if
     // you find out how this can be achieved.
     throw nb::type_error(
-        "APyFixedArray::_set_bits_from_numpy_ndarray(): "
+        "APyFixedArray::_set_bits_from_ndarray(): "
         "expecting integer `dtype`"
     );
 }
 
-void APyFixedArray::_set_values_from_ndarray(const nb::ndarray<>& ndarray)
+void APyFixedArray::_set_values_from_ndarray(const nb::ndarray<nb::c_contig>& ndarray)
 {
 #define CHECK_AND_SET_VALUES_FROM_NPTYPE(__TYPE__)                                     \
     do {                                                                               \
@@ -1488,7 +1488,7 @@ void APyFixedArray::_set_values_from_ndarray(const nb::ndarray<>& ndarray)
                     );                                                                 \
                 }                                                                      \
             }                                                                          \
-            return; /* Conversion completed, exit function */                          \
+            return; /* Conversion completed, exit `_set_values_from_ndarray()` */      \
         }                                                                              \
     } while (0)
 
diff --git a/src/apyfixedarray.h b/src/apyfixedarray.h
index 4bcc983db..2988d2a60 100644
--- a/src/apyfixedarray.h
+++ b/src/apyfixedarray.h
@@ -203,7 +203,7 @@ class APyFixedArray : public APyBuffer<mp_limb_t> {
 
     //! Create an `APyFixedArray` tensor object initialized with values from an ndarray
     static APyFixedArray from_array(
-        const nanobind::ndarray<>& double_seq,
+        const nanobind::ndarray<nanobind::c_contig>& double_seq,
         std::optional<int> int_bits = std::nullopt,
         std::optional<int> frac_bits = std::nullopt,
         std::optional<int> bits = std::nullopt
@@ -315,20 +315,18 @@ class APyFixedArray : public APyBuffer<mp_limb_t> {
     ) const;
 
     /*!
-     * Set the underlying bit values of `*this` from a NumPy NDArray object of
-     * integers. This member function assumes that the shape of `*this` and `ndarray`
-     * are equal.
+     * Set the underlying bit values of `*this` from a NDArray object of integers. This
+     * member function assumes that the shape of `*this` and `ndarray` are equal.
      */
-    void _set_bits_from_numpy_ndarray(const nanobind::ndarray<nanobind::numpy>& ndarray
-    );
+    void _set_bits_from_ndarray(const nanobind::ndarray<nanobind::c_contig>& ndarray);
 
     /*!
-     * Set the values of `*this` from a NumPy NDArray object of floats/integers. This
-     * member function assumes that the shape of `*this` and `ndarray` are equal. The
-     * elements in `ndarray` are explicitly converted to `double` before being copied
-     * into `*this`.
+     * Set the values of `*this` from a NDArray object of floats/integers. This member
+     * function assumes that the shape of `*this` and `ndarray` are equal. The elements
+     * in `ndarray` are explicitly converted to `double` before being copied into
+     * `*this`.
      */
-    void _set_values_from_ndarray(const nanobind::ndarray<>& ndarray);
+    void _set_values_from_ndarray(const nanobind::ndarray<nanobind::c_contig>& ndarray);
 
     //! Check if object are of the same type, i.e., same number of bits.
     APY_INLINE bool same_type_as(const APyFixedArray& other) const
diff --git a/src/apyfixedarray_wrapper.cc b/src/apyfixedarray_wrapper.cc
index 1c2a2097f..b1c146c5d 100644
--- a/src/apyfixedarray_wrapper.cc
+++ b/src/apyfixedarray_wrapper.cc
@@ -316,8 +316,8 @@ void bind_fixed_array(nb::module_& m)
             This is the primary method for performing quantization and overflowing/saturation
             when dealing with APyTypes fixed-point arrays.
 
-            Exactly two of three bit-specifiers (*bits*, *int_bits*, *frac_bits*) needs
-            to be set.
+            Exactly two of three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must
+            be set.
 
             Parameters
             ----------
@@ -352,8 +352,8 @@ void bind_fixed_array(nb::module_& m)
             Create an :class:`APyFixedArray` object from a sequence of :class:`float`.
 
             The initialized fixed-point values are the one closest to the
-            input floating-point value, rounded away from zero on ties. Exactly two of
-            the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) has to be set.
+            input floating-point values, rounded away from zero on ties. Exactly two of
+            the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be set.
 
             Using NumPy arrays as input is in general faster than e.g. lists.
 
@@ -406,7 +406,7 @@ void bind_fixed_array(nb::module_& m)
 
             The initialized fixed-point values are the one closest to the
             input floating-point value, rounded away from zero on ties. Exactly two of
-            the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) has to be set.
+            the three bit-specifiers (`bits`, `int_bits`, `frac_bits`) must be set.
 
             Using NumPy arrays as input is in general faster than e.g. lists.
 
@@ -425,6 +425,23 @@ void bind_fixed_array(nb::module_& m)
             -------
             :class:`APyFixedArray`
 
+            Examples
+            --------
+
+            .. code-block:: python
+
+                from apytypes import APyFixedArray
+                import numpy as np
+
+                # Array `a`, initialized from NumPy ndarray
+                a = APyFixedArray.from_array(
+                    np.array([
+                        [1.0, 2.0, 3.0],
+                        [4.0, 5.0, 6.0],
+                    ]),
+                    int_bits=10,
+                    frac_bits=0
+                )
             )pbdoc"
         )
 
diff --git a/src/apyfloatarray.cc b/src/apyfloatarray.cc
index 84157c206..2f1c038f9 100644
--- a/src/apyfloatarray.cc
+++ b/src/apyfloatarray.cc
@@ -1044,15 +1044,15 @@ bool APyFloatArray::is_identical(const APyFloatArray& other) const
 }
 
 APyFloatArray APyFloatArray::from_double(
-    const nanobind::sequence& double_seq,
+    const nb::sequence& double_seq,
     std::uint8_t exp_bits,
     std::uint8_t man_bits,
     std::optional<exp_t> bias
 )
 {
-    if (nb::isinstance<nb::ndarray<nb::numpy>>(double_seq)) {
-        // Sequence is NumPy NDArray. Initialize using `from_array`.
-        auto ndarray = nb::cast<nb::ndarray<>>(double_seq);
+    if (nb::isinstance<nb::ndarray<>>(double_seq)) {
+        // Sequence is NDArray. Initialize using `from_array`.
+        auto ndarray = nb::cast<nb::ndarray<nb::c_contig>>(double_seq);
         return from_array(ndarray, exp_bits, man_bits, bias);
     }
 
@@ -1089,7 +1089,7 @@ APyFloatArray APyFloatArray::from_double(
 }
 
 APyFloatArray APyFloatArray::from_array(
-    const nanobind::ndarray<>& ndarray,
+    const nb::ndarray<nb::c_contig>& ndarray,
     std::uint8_t exp_bits,
     std::uint8_t man_bits,
     std::optional<exp_t> bias
@@ -1113,7 +1113,7 @@ APyFloatArray APyFloatArray::from_array(
     return result;
 }
 
-void APyFloatArray::_set_values_from_ndarray(const nb::ndarray<>& ndarray)
+void APyFloatArray::_set_values_from_ndarray(const nb::ndarray<nb::c_contig>& ndarray)
 {
     // Double value used for converting.
     APyFloat double_caster(11, 52, 1023);
diff --git a/src/apyfloatarray.h b/src/apyfloatarray.h
index e4f6c7b27..fbbcebbc3 100644
--- a/src/apyfloatarray.h
+++ b/src/apyfloatarray.h
@@ -1,4 +1,3 @@
-
 #ifndef _APYFLOAT_ARRAY_H
 #define _APYFLOAT_ARRAY_H
 
@@ -104,13 +103,13 @@ class APyFloatArray {
 
     //! Create an `APyFloatArray` tensor object initialized with values from an ndarray
     static APyFloatArray from_array(
-        const nanobind::ndarray<>& ndarray,
+        const nanobind::ndarray<nanobind::c_contig>& ndarray,
         std::uint8_t exp_bits,
         std::uint8_t man_bits,
         std::optional<exp_t> bias = std::nullopt
     );
 
-    void _set_values_from_ndarray(const nanobind::ndarray<>& ndarray);
+    void _set_values_from_ndarray(const nanobind::ndarray<nanobind::c_contig>& ndarray);
 
     //! Transposition function. For a 1-D array, returns an exact copy of `*this`. For
     //! a 2-D array, returns the matrix transposition of `*this`.
diff --git a/src/apyfloatarray_wrapper.cc b/src/apyfloatarray_wrapper.cc
index 644cc141d..ff62ee417 100644
--- a/src/apyfloatarray_wrapper.cc
+++ b/src/apyfloatarray_wrapper.cc
@@ -312,8 +312,8 @@ void bind_float_array(nb::module_& m)
             "from_float",
             &APyFloatArray::from_double,
             nb::arg("float_sequence"),
-            nb::arg("exp_bits") = nb::none(),
-            nb::arg("man_bits") = nb::none(),
+            nb::arg("exp_bits"),
+            nb::arg("man_bits"),
             nb::arg("bias") = nb::none(),
             R"pbdoc(
             Create an :class:`APyFloatArray` object from a sequence of :class:`float`.
@@ -325,7 +325,7 @@ void bind_float_array(nb::module_& m)
                 from the sequence shape.
             exp_bits : int
                 Number of exponent bits in the created fixed-point tensor
-            man_bits : int, optional
+            man_bits : int
                 Number of mantissa bits in the created fixed-point tensor
             bias : int, optional
                 Bias in the created fixed-point tensor
@@ -359,8 +359,8 @@ void bind_float_array(nb::module_& m)
             "from_array",
             &APyFloatArray::from_array,
             nb::arg("ndarray"),
-            nb::arg("exp_bits") = nb::none(),
-            nb::arg("man_bits") = nb::none(),
+            nb::arg("exp_bits"),
+            nb::arg("man_bits"),
             nb::arg("bias") = nb::none(),
             R"pbdoc(
             Create an :class:`APyFloatArray` object from an ndarray.
@@ -371,7 +371,7 @@ void bind_float_array(nb::module_& m)
                 Values to initialize from. The tensor shape will be taken from the ndarray shape.
             exp_bits : int
                 Number of exponent bits in the created fixed-point tensor
-            man_bits : int, optional
+            man_bits : int
                 Number of mantissa bits in the created fixed-point tensor
             bias : int, optional
                 Bias in the created fixed-point tensor
@@ -380,6 +380,24 @@ void bind_float_array(nb::module_& m)
             -------
             :class:`APyFloatArray`
 
+            Examples
+            --------
+
+            .. code-block:: python
+
+                from apytypes import APyFloatArray
+                import numpy as np
+
+                # Array `a`, initialized from NumPy ndarray
+                a = APyFloatArray.from_array(
+                    np.array([
+                        [1.0, 2.0, 3.0],
+                        [4.0, 5.0, 6.0],
+                    ]),
+                    man_bits=10,
+                    exp_bits=10
+                )
+
             )pbdoc"
         )
 


Test patch:
diff --git a/lib/test/apyfixedarray/test_constructors.py b/lib/test/apyfixedarray/test_constructors.py
index b9e289840..f5c456d7b 100644
--- a/lib/test/apyfixedarray/test_constructors.py
+++ b/lib/test/apyfixedarray/test_constructors.py
@@ -163,5 +163,34 @@ def test_from_numpy_raises():
     with pytest.raises(TypeError, match="APyFixedArray::_set_values_from_ndarray"):
         b = APyFixedArray.from_float(a, 14, 4)
     a = np.asarray([[0.0, 1.0]])
-    with pytest.raises(TypeError, match="APyFixedArray::_set_bits_from_numpy_ndarray"):
+    with pytest.raises(TypeError, match="APyFixedArray::_set_bits_from_ndarray"):
         b = APyFixedArray(a, 14, 4)
+
+
+def test_c_striding():
+    np = pytest.importorskip("numpy")
+    a = np.array([[1, 2, 3], [4, 5, 6]])
+
+    # `from_float()`
+    assert APyFixedArray.from_float(a, int_bits=10, frac_bits=0).is_identical(
+        APyFixedArray([[1, 2, 3], [4, 5, 6]], int_bits=10, frac_bits=0)
+    )
+    assert APyFixedArray.from_float(a.T, int_bits=10, frac_bits=0).is_identical(
+        APyFixedArray([[1, 4], [2, 5], [3, 6]], int_bits=10, frac_bits=0)
+    )
+
+    # `from_array()`
+    assert APyFixedArray.from_array(a, int_bits=10, frac_bits=0).is_identical(
+        APyFixedArray([[1, 2, 3], [4, 5, 6]], int_bits=10, frac_bits=0)
+    )
+    assert APyFixedArray.from_array(a.T, int_bits=10, frac_bits=0).is_identical(
+        APyFixedArray([[1, 4], [2, 5], [3, 6]], int_bits=10, frac_bits=0)
+    )
+
+    # `__init__()`
+    assert APyFixedArray(a, int_bits=10, frac_bits=0).is_identical(
+        APyFixedArray([[1, 2, 3], [4, 5, 6]], int_bits=10, frac_bits=0)
+    )
+    assert APyFixedArray(a.T, int_bits=10, frac_bits=0).is_identical(
+        APyFixedArray([[1, 4], [2, 5], [3, 6]], int_bits=10, frac_bits=0)
+    )
diff --git a/lib/test/apyfloatarray/test_constructors.py b/lib/test/apyfloatarray/test_constructors.py
index 21bce436f..74e3e3b87 100644
--- a/lib/test/apyfloatarray/test_constructors.py
+++ b/lib/test/apyfloatarray/test_constructors.py
@@ -146,3 +146,24 @@ def test_from_numpy_raises():
     a = np.asarray([[1e-323, float("inf")], [float("nan"), 0.0]], dtype="half")
     with pytest.raises(TypeError, match="APyFloatArray::_set_values_from_ndarray"):
         b = APyFloatArray.from_float(a, 14, 60)
+
+
+def test_c_striding():
+    np = pytest.importorskip("numpy")
+    a = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
+
+    # `from_float()`
+    assert APyFloatArray.from_float(a, man_bits=10, exp_bits=10).is_identical(
+        APyFloatArray.from_float([[1, 2, 3], [4, 5, 6]], man_bits=10, exp_bits=10)
+    )
+    assert APyFloatArray.from_float(a.T, man_bits=10, exp_bits=10).is_identical(
+        APyFloatArray.from_float([[1, 4], [2, 5], [3, 6]], man_bits=10, exp_bits=10)
+    )
+
+    # `from_array()`
+    assert APyFloatArray.from_array(a, man_bits=10, exp_bits=10).is_identical(
+        APyFloatArray.from_float([[1, 2, 3], [4, 5, 6]], man_bits=10, exp_bits=10)
+    )
+    assert APyFloatArray.from_array(a.T, man_bits=10, exp_bits=10).is_identical(
+        APyFloatArray.from_float([[1, 4], [2, 5], [3, 6]], man_bits=10, exp_bits=10)
+    )