Merge branch 'master' into byteswap

This commit is contained in:
Zoltán Vörös 2021-02-14 09:36:07 +01:00 committed by GitHub
commit efcfeff790
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 584 additions and 511 deletions

View file

@ -6,6 +6,16 @@ dimensions, and is fast. The library is a software-only standard `micropython` u
i.e., it has no hardware dependencies, and can be compiled for any platform.
The `float` implementation of `micropython` (`float`, or `double`) is automatically detected.
1. [Supported functions](#supported-functions)
1. [ndarray](#ndarray)
1. [Usage](#usage)
1. [Customising the firmware](#customising-the-firmware)
1. [Finding help](#finding-help)
1. [Benchmarks](#benchmarks)
1. [Firmware](#firmware)
1. [Issues, contributing, and testing](#issues-contributing-and-testing)
1. [Testing](#testing)
# Supported functions
@ -21,7 +31,7 @@ iterables via the `array` constructor, or by means of the `arange`, `concatenate
`shape`, `size`, `strides`, `tobytes`, and `transpose`.
## Customising the firmware
# Customising the firmware
In addition to the `ndarray` operators and methods, `ulab` defines a great number of functions that can
take `ndarray`s or `micropython` iterables as their arguments. Most of the functions have been ported from
@ -37,7 +47,7 @@ of the user manual.
It is also possible to extend the library with arbitrary user-defined functions operating on numerical arrays, and add them to the namespace, as explaind in the [programming manual](https://micropython-ulab.readthedocs.io/en/latest/ulab-programming.html).
## Usage
# Usage
`ulab` sports a `numpy/scipy`-compatible interface, which makes porting of `CPython` code straightforward. The following
snippet should run equally well in `micropython`, or on a PC.
@ -224,3 +234,22 @@ If it compiles without error, you can plug in your ESP32 via USB and then flash
```bash
make erase && make deploy
```
# Issues, contributing, and testing
If you find a problem with the code, please, raise an [issue](https://github.com/v923z/micropython-ulab/issues)! An issue should address a single problem, and should contain a minimal code snippet that demonstrates the difference from the expected behaviour. Reducing a problem to the bare minimum significantly increases the chances of a quick fix.
Feature requests (porting a particular function from `numpy` or `scipy`) should also be posted at [ulab issue](https://github.com/v923z/micropython-ulab/issues).
Contributions of any kind are always welcome. If you feel like adding to the code, you can simply issue a pull request. If you do so, please, try to adhere to `micropython`'s [coding conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md#c-code-conventions).
However, you can also contribute to the documentation (preferably via the [jupyter notebooks](https://github.com/v923z/micropython-ulab/tree/master/docs), or improve the [tests](https://github.com/v923z/micropython-ulab/tree/master/tests).
## Testing
If you decide to lend a hand with testing, here are the steps:
1. Write a test script that checks a particular function, or a set of related functions!
1. Drop this script in one of the folders in [ulab tests](https://github.com/v923z/micropython-ulab/tree/master/tests)!
1. Run the [./build.sh](https://github.com/v923z/micropython-ulab/blob/master/build.sh) script in the root directory of `ulab`! This will clone the latest `micropython`, compile the firmware for `unix`, execute all scripts in the `ulab/tests`, and compare the results to those in the expected results files, which are also in `ulab/tests`, and have an extension `.exp`. In case you have a new snippet, i.e., you have no expected results file, or if the results differ from those in the expected file, a new expected file will be generated in the root directory. You should inspect the contents of this file, and if they are satisfactory, then the file can be moved to the `ulab/tests` folder, alongside your snippet.

View file

@ -19,6 +19,7 @@ SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg_tools.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/numerical/numerical.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/poly/poly.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/stats/stats.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/transform/transform.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/vector/vector.c
SRC_USERMOD += $(USERMODULES_DIR)/user/user.c

View file

@ -28,21 +28,6 @@
//| """Linear algebra functions"""
//|
#if ULAB_MAX_DIMS > 1
static ndarray_obj_t *linalg_object_is_square(mp_obj_t obj) {
// Returns an ndarray, if the object is a square ndarray,
// raises the appropriate exception otherwise
if(!MP_OBJ_IS_TYPE(obj, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("size is defined for ndarrays only"));
}
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(obj);
if((ndarray->shape[ULAB_MAX_DIMS - 1] != ndarray->shape[ULAB_MAX_DIMS - 2]) || (ndarray->ndim != 2)) {
mp_raise_ValueError(translate("input must be square matrix"));
}
return ndarray;
}
#endif
#if ULAB_MAX_DIMS > 1
//| def cholesky(A: ulab.array) -> ulab.array:
//| """
@ -55,7 +40,7 @@ static ndarray_obj_t *linalg_object_is_square(mp_obj_t obj) {
//|
static mp_obj_t linalg_cholesky(mp_obj_t oin) {
ndarray_obj_t *ndarray = linalg_object_is_square(oin);
ndarray_obj_t *ndarray = tools_object_is_square(oin);
ndarray_obj_t *L = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, ndarray->shape[ULAB_MAX_DIMS - 1], ndarray->shape[ULAB_MAX_DIMS - 1]), NDARRAY_FLOAT);
mp_float_t *Larray = (mp_float_t *)L->array;
@ -121,7 +106,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_cholesky_obj, linalg_cholesky);
//|
static mp_obj_t linalg_det(mp_obj_t oin) {
ndarray_obj_t *ndarray = linalg_object_is_square(oin);
ndarray_obj_t *ndarray = tools_object_is_square(oin);
uint8_t *array = (uint8_t *)ndarray->array;
size_t N = ndarray->shape[ULAB_MAX_DIMS - 1];
mp_float_t *tmp = m_new(mp_float_t, N * N);
@ -182,70 +167,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_det_obj, linalg_det);
#endif
//| def dot(m1: ulab.array, m2: ulab.array) -> Union[ulab.array, float]:
//| """
//| :param ~ulab.array m1: a matrix, or a vector
//| :param ~ulab.array m2: a matrix, or a vector
//|
//| Computes the product of two matrices, or two vectors. In the letter case, the inner product is returned."""
//| ...
//|
static mp_obj_t linalg_dot(mp_obj_t _m1, mp_obj_t _m2) {
// TODO: should the results be upcast?
// This implements 2D operations only!
if(!MP_OBJ_IS_TYPE(_m1, &ulab_ndarray_type) || !MP_OBJ_IS_TYPE(_m2, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("arguments must be ndarrays"));
}
ndarray_obj_t *m1 = MP_OBJ_TO_PTR(_m1);
ndarray_obj_t *m2 = MP_OBJ_TO_PTR(_m2);
#if ULAB_MAX_DIMS > 1
if ((m1->ndim == 1) && (m2->ndim == 1)) {
#endif
// 2 vectors
if (m1->len != m2->len) {
mp_raise_ValueError(translate("vectors must have same lengths"));
}
mp_float_t dot = 0.0;
uint8_t *array1 = (uint8_t *)m1->array;
uint8_t *array2 = (uint8_t *)m2->array;
for (size_t i=0; i < m1->len; i++) {
dot += ndarray_get_float_value(array1, m1->dtype)*ndarray_get_float_value(array2, m2->dtype);
array1 += m1->strides[ULAB_MAX_DIMS - 1];
array2 += m2->strides[ULAB_MAX_DIMS - 1];
}
return mp_obj_new_float(dot);
#if ULAB_MAX_DIMS > 1
} else {
// 2 matrices
if(m1->shape[ULAB_MAX_DIMS - 1] != m2->shape[ULAB_MAX_DIMS - 2]) {
mp_raise_ValueError(translate("matrix dimensions do not match"));
}
size_t *shape = ndarray_shape_vector(0, 0, m1->shape[ULAB_MAX_DIMS - 2], m2->shape[ULAB_MAX_DIMS - 1]);
ndarray_obj_t *out = ndarray_new_dense_ndarray(2, shape, NDARRAY_FLOAT);
mp_float_t *outdata = (mp_float_t *)out->array;
for(size_t i=0; i < m1->shape[ULAB_MAX_DIMS - 2]; i++) { // rows of m1
for(size_t j=0; j < m2->shape[ULAB_MAX_DIMS - 1]; j++) { // columns of m2
mp_float_t sum = 0.0, v1, v2;
for(size_t k=0; k < m2->shape[ULAB_MAX_DIMS - 2]; k++) {
// (i, k) * (k, j)
size_t pos1 = i*m1->shape[ULAB_MAX_DIMS - 1]+k;
size_t pos2 = k*m2->shape[ULAB_MAX_DIMS - 1]+j;
v1 = ndarray_get_float_index(m1->array, m1->dtype, pos1);
v2 = ndarray_get_float_index(m2->array, m2->dtype, pos2);
sum += v1 * v2;
}
*outdata++ = sum;
}
}
return MP_OBJ_FROM_PTR(out);
}
#endif
}
MP_DEFINE_CONST_FUN_OBJ_2(linalg_dot_obj, linalg_dot);
#if ULAB_MAX_DIMS > 1
//| def eig(m: ulab.array) -> Tuple[ulab.array, ulab.array]:
//| """
@ -257,7 +178,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(linalg_dot_obj, linalg_dot);
//|
static mp_obj_t linalg_eig(mp_obj_t oin) {
ndarray_obj_t *in = linalg_object_is_square(oin);
ndarray_obj_t *in = tools_object_is_square(oin);
uint8_t *iarray = (uint8_t *)in->array;
size_t S = in->shape[ULAB_MAX_DIMS - 1];
mp_float_t *array = m_new(mp_float_t, S*S);
@ -318,7 +239,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_eig_obj, linalg_eig);
//| ...
//|
static mp_obj_t linalg_inv(mp_obj_t o_in) {
ndarray_obj_t *ndarray = linalg_object_is_square(o_in);
ndarray_obj_t *ndarray = tools_object_is_square(o_in);
uint8_t *array = (uint8_t *)ndarray->array;
size_t N = ndarray->shape[ULAB_MAX_DIMS - 1];
ndarray_obj_t *inverted = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, N, N), NDARRAY_FLOAT);
@ -442,55 +363,21 @@ static mp_obj_t linalg_norm(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
MP_DEFINE_CONST_FUN_OBJ_KW(linalg_norm_obj, 1, linalg_norm);
// MP_DEFINE_CONST_FUN_OBJ_1(linalg_norm_obj, linalg_norm);
#if ULAB_MAX_DIMS > 1
#if ULAB_LINALG_HAS_TRACE
//| def trace(m: ulab.array) -> float:
//| """
//| :param m: a square matrix
//|
//| Compute the trace of the matrix, the sum of its diagonal elements."""
//| ...
//|
static mp_obj_t linalg_trace(mp_obj_t oin) {
ndarray_obj_t *ndarray = linalg_object_is_square(oin);
mp_float_t trace = 0.0;
for(size_t i=0; i < ndarray->shape[ULAB_MAX_DIMS - 1]; i++) {
int32_t pos = i * (ndarray->strides[ULAB_MAX_DIMS - 1] + ndarray->strides[ULAB_MAX_DIMS - 2]);
trace += ndarray_get_float_index(ndarray->array, ndarray->dtype, pos/ndarray->itemsize);
}
if(ndarray->dtype == NDARRAY_FLOAT) {
return mp_obj_new_float(trace);
}
return mp_obj_new_int_from_float(trace);
}
MP_DEFINE_CONST_FUN_OBJ_1(linalg_trace_obj, linalg_trace);
#endif
#endif
STATIC const mp_rom_map_elem_t ulab_linalg_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_linalg) },
#if ULAB_MAX_DIMS > 1
#if ULAB_LINALG_HAS_CHOLESKY
{ MP_ROM_QSTR(MP_QSTR_cholesky), (mp_obj_t)&linalg_cholesky_obj },
#endif
#if ULAB_LINALG_HAS_DET
{ MP_ROM_QSTR(MP_QSTR_det), (mp_obj_t)&linalg_det_obj },
#endif
#if ULAB_LINALG_HAS_EIG
{ MP_ROM_QSTR(MP_QSTR_eig), (mp_obj_t)&linalg_eig_obj },
#endif
#if ULAB_LINALG_HAS_INV
{ MP_ROM_QSTR(MP_QSTR_inv), (mp_obj_t)&linalg_inv_obj },
#endif
#if ULAB_LINALG_HAS_TRACE
{ MP_ROM_QSTR(MP_QSTR_trace), (mp_obj_t)&linalg_trace_obj },
#endif
#endif
#if ULAB_LINALG_HAS_DOT
{ MP_ROM_QSTR(MP_QSTR_dot), (mp_obj_t)&linalg_dot_obj },
#if ULAB_LINALG_HAS_CHOLESKY
{ MP_ROM_QSTR(MP_QSTR_cholesky), (mp_obj_t)&linalg_cholesky_obj },
#endif
#if ULAB_LINALG_HAS_DET
{ MP_ROM_QSTR(MP_QSTR_det), (mp_obj_t)&linalg_det_obj },
#endif
#if ULAB_LINALG_HAS_EIG
{ MP_ROM_QSTR(MP_QSTR_eig), (mp_obj_t)&linalg_eig_obj },
#endif
#if ULAB_LINALG_HAS_INV
{ MP_ROM_QSTR(MP_QSTR_inv), (mp_obj_t)&linalg_inv_obj },
#endif
#endif
#if ULAB_LINALG_HAS_NORM
{ MP_ROM_QSTR(MP_QSTR_norm), (mp_obj_t)&linalg_norm_obj },

View file

@ -22,7 +22,5 @@ MP_DECLARE_CONST_FUN_OBJ_1(linalg_cholesky_obj);
MP_DECLARE_CONST_FUN_OBJ_1(linalg_det_obj);
MP_DECLARE_CONST_FUN_OBJ_1(linalg_eig_obj);
MP_DECLARE_CONST_FUN_OBJ_1(linalg_inv_obj);
MP_DECLARE_CONST_FUN_OBJ_1(linalg_trace_obj);
MP_DECLARE_CONST_FUN_OBJ_2(linalg_dot_obj);
MP_DECLARE_CONST_FUN_OBJ_KW(linalg_norm_obj);
#endif

View file

@ -24,6 +24,8 @@
#include "filter/filter.h"
#include "linalg/linalg.h"
#include "numerical/numerical.h"
#include "stats/stats.h"
#include "transform/transform.h"
#include "poly/poly.h"
#include "vector/vector.h"
@ -168,6 +170,12 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
#if ULAB_NUMPY_HAS_DIFF
{ MP_OBJ_NEW_QSTR(MP_QSTR_diff), (mp_obj_t)&numerical_diff_obj },
#endif
#if ULAB_NUMPY_HAS_DOT
{ MP_OBJ_NEW_QSTR(MP_QSTR_dot), (mp_obj_t)&transform_dot_obj },
#endif
#if ULAB_NUMPY_HAS_TRACE
{ MP_ROM_QSTR(MP_QSTR_trace), (mp_obj_t)&stats_trace_obj },
#endif
#if ULAB_NUMPY_HAS_FLIP
{ MP_OBJ_NEW_QSTR(MP_QSTR_flip), (mp_obj_t)&numerical_flip_obj },
#endif

View file

@ -22,3 +22,31 @@
#include "../../ulab.h"
#include "../../ulab_tools.h"
#include "stats.h"
#if ULAB_MAX_DIMS > 1
#if ULAB_NUMPY_HAS_TRACE
//| def trace(m: ulab.array) -> float:
//| """
//| :param m: a square matrix
//|
//| Compute the trace of the matrix, the sum of its diagonal elements."""
//| ...
//|
static mp_obj_t stats_trace(mp_obj_t oin) {
ndarray_obj_t *ndarray = tools_object_is_square(oin);
mp_float_t trace = 0.0;
for(size_t i=0; i < ndarray->shape[ULAB_MAX_DIMS - 1]; i++) {
int32_t pos = i * (ndarray->strides[ULAB_MAX_DIMS - 1] + ndarray->strides[ULAB_MAX_DIMS - 2]);
trace += ndarray_get_float_index(ndarray->array, ndarray->dtype, pos/ndarray->itemsize);
}
if(ndarray->dtype == NDARRAY_FLOAT) {
return mp_obj_new_float(trace);
}
return mp_obj_new_int_from_float(trace);
}
MP_DEFINE_CONST_FUN_OBJ_1(stats_trace_obj, stats_trace);
#endif
#endif

View file

@ -15,4 +15,6 @@
#include "../../ulab.h"
#include "../../ndarray.h"
MP_DECLARE_CONST_FUN_OBJ_1(stats_trace_obj);
#endif

View file

@ -0,0 +1,88 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2019-2021 Zoltán Vörös
*
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/misc.h"
#include "../../ulab.h"
#include "../../ulab_tools.h"
#include "transform.h"
#if ULAB_NUMPY_HAS_DOT
//| def dot(m1: ulab.array, m2: ulab.array) -> Union[ulab.array, float]:
//| """
//| :param ~ulab.array m1: a matrix, or a vector
//| :param ~ulab.array m2: a matrix, or a vector
//|
//| Computes the product of two matrices, or two vectors. In the letter case, the inner product is returned."""
//| ...
//|
mp_obj_t transform_dot(mp_obj_t _m1, mp_obj_t _m2) {
// TODO: should the results be upcast?
// This implements 2D operations only!
if(!MP_OBJ_IS_TYPE(_m1, &ulab_ndarray_type) || !MP_OBJ_IS_TYPE(_m2, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("arguments must be ndarrays"));
}
ndarray_obj_t *m1 = MP_OBJ_TO_PTR(_m1);
ndarray_obj_t *m2 = MP_OBJ_TO_PTR(_m2);
#if ULAB_MAX_DIMS > 1
if ((m1->ndim == 1) && (m2->ndim == 1)) {
#endif
// 2 vectors
if (m1->len != m2->len) {
mp_raise_ValueError(translate("vectors must have same lengths"));
}
mp_float_t dot = 0.0;
uint8_t *array1 = (uint8_t *)m1->array;
uint8_t *array2 = (uint8_t *)m2->array;
for (size_t i=0; i < m1->len; i++) {
dot += ndarray_get_float_value(array1, m1->dtype)*ndarray_get_float_value(array2, m2->dtype);
array1 += m1->strides[ULAB_MAX_DIMS - 1];
array2 += m2->strides[ULAB_MAX_DIMS - 1];
}
return mp_obj_new_float(dot);
#if ULAB_MAX_DIMS > 1
} else {
// 2 matrices
if(m1->shape[ULAB_MAX_DIMS - 1] != m2->shape[ULAB_MAX_DIMS - 2]) {
mp_raise_ValueError(translate("matrix dimensions do not match"));
}
size_t *shape = ndarray_shape_vector(0, 0, m1->shape[ULAB_MAX_DIMS - 2], m2->shape[ULAB_MAX_DIMS - 1]);
ndarray_obj_t *out = ndarray_new_dense_ndarray(2, shape, NDARRAY_FLOAT);
mp_float_t *outdata = (mp_float_t *)out->array;
for(size_t i=0; i < m1->shape[ULAB_MAX_DIMS - 2]; i++) { // rows of m1
for(size_t j=0; j < m2->shape[ULAB_MAX_DIMS - 1]; j++) { // columns of m2
mp_float_t sum = 0.0, v1, v2;
for(size_t k=0; k < m2->shape[ULAB_MAX_DIMS - 2]; k++) {
// (i, k) * (k, j)
size_t pos1 = i*m1->shape[ULAB_MAX_DIMS - 1]+k;
size_t pos2 = k*m2->shape[ULAB_MAX_DIMS - 1]+j;
v1 = ndarray_get_float_index(m1->array, m1->dtype, pos1);
v2 = ndarray_get_float_index(m2->array, m2->dtype, pos2);
sum += v1 * v2;
}
*outdata++ = sum;
}
}
return MP_OBJ_FROM_PTR(out);
}
#endif
}
MP_DEFINE_CONST_FUN_OBJ_2(transform_dot_obj, transform_dot);
#endif

View file

@ -0,0 +1,28 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2019-2021 Zoltán Vörös
*
*/
#ifndef _TRANSFORM_
#define _TRANSFORM_
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/misc.h"
#include "../../ulab.h"
#include "../../ulab_tools.h"
#include "transform.h"
MP_DECLARE_CONST_FUN_OBJ_2(transform_dot_obj);
#endif

View file

@ -345,10 +345,6 @@
#define ULAB_LINALG_HAS_DET (1)
#endif
#ifndef ULAB_LINALG_HAS_DOT
#define ULAB_LINALG_HAS_DOT (1)
#endif
#ifndef ULAB_LINALG_HAS_EIG
#define ULAB_LINALG_HAS_EIG (1)
#endif
@ -361,10 +357,6 @@
#define ULAB_LINALG_HAS_NORM (1)
#endif
#ifndef ULAB_LINALG_HAS_TRACE
#define ULAB_LINALG_HAS_TRACE (1)
#endif
// the FFT module; functions of the fft module still have
// to be defined separately
#ifndef ULAB_NUMPY_HAS_FFT_MODULE
@ -407,6 +399,10 @@
#define ULAB_NUMPY_HAS_DIFF (1)
#endif
#ifndef ULAB_NUMPY_HAS_DOT
#define ULAB_NUMPY_HAS_DOT (1)
#endif
#ifndef ULAB_NUMPY_HAS_FLIP
#define ULAB_NUMPY_HAS_FLIP (1)
#endif
@ -451,6 +447,10 @@
#define ULAB_NUMPY_HAS_SUM (1)
#endif
#ifndef ULAB_NUMPY_HAS_TRACE
#define ULAB_NUMPY_HAS_TRACE (1)
#endif
#ifndef ULAB_NUMPY_HAS_TRAPZ
#define ULAB_NUMPY_HAS_TRAPZ (1)
#endif

View file

@ -669,10 +669,13 @@ mp_obj_t create_frombuffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
len = count;
}
}
ndarray_obj_t *ndarray = ndarray_new_linear_array(len, dtype);
uint8_t *array = (uint8_t *)ndarray->array;
ndarray_obj_t *ndarray = ndarray_new_linear_array(1, dtype);
// at this point, ndarray->len = 1, ndarray->shape[ULAB_MAX_DIMS - 1] = 1
uint8_t *buffer = bufinfo.buf;
memcpy(array, buffer + offset, len * sz);
ndarray->array = buffer + offset;
// fix the length and shape here
ndarray->len = len;
ndarray->shape[ULAB_MAX_DIMS - 1] = len;
return MP_OBJ_FROM_PTR(ndarray);
}
return mp_const_none;

View file

@ -212,3 +212,19 @@ shape_strides tools_reduce_axes(ndarray_obj_t *ndarray, mp_obj_t axis) {
return _shape_strides;
}
#if ULAB_MAX_DIMS > 1
ndarray_obj_t *tools_object_is_square(mp_obj_t obj) {
// Returns an ndarray, if the object is a square ndarray,
// raises the appropriate exception otherwise
if(!MP_OBJ_IS_TYPE(obj, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("size is defined for ndarrays only"));
}
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(obj);
if((ndarray->shape[ULAB_MAX_DIMS - 1] != ndarray->shape[ULAB_MAX_DIMS - 2]) || (ndarray->ndim != 2)) {
mp_raise_ValueError(translate("input must be square matrix"));
}
return ndarray;
}
#endif

View file

@ -33,4 +33,5 @@ uint8_t ndarray_upcast_dtype(uint8_t , uint8_t );
void *ndarray_set_float_function(uint8_t );
shape_strides tools_reduce_axes(ndarray_obj_t *, mp_obj_t );
ndarray_obj_t *tools_object_is_square(mp_obj_t );
#endif

View file

@ -27,7 +27,7 @@ copyright = '2019-2021, Zoltán Vörös and contributors'
author = 'Zoltán Vörös'
# The full version, including alpha/beta/rc tags
release = '2.3.0'
release = '2.3.6'
# -- General configuration ---------------------------------------------------

View file

@ -13,25 +13,27 @@ from ``numpy``.
6. `numpy.clip <#clip>`__
7. `numpy.convolve <#convolve>`__
8. `numpy.diff <#diff>`__
9. `numpy.equal <#equal>`__
10. `numpy.flip <#flip>`__
11. `numpy.interp <#interp>`__
12. `numpy.isfinite <#isfinite>`__
13. `numpy.isinf <#isinf>`__
14. `numpy.max <#max>`__
15. `numpy.maximum <#maximum>`__
16. `numpy.mean <#mean>`__
17. `numpy.median <#median>`__
18. `numpy.min <#min>`__
19. `numpy.minimum <#minimum>`__
20. `numpy.not_equal <#equal>`__
21. `numpy.polyfit <#polyfit>`__
22. `numpy.polyval <#polyval>`__
23. `numpy.roll <#roll>`__
24. `numpy.sort <#sort>`__
25. `numpy.std <#std>`__
26. `numpy.sum <#sum>`__
27. `numpy.trapz <#trapz>`__
9. `numpy.dot <#dot>`__
10. `numpy.equal <#equal>`__
11. `numpy.flip <#flip>`__
12. `numpy.interp <#interp>`__
13. `numpy.isfinite <#isfinite>`__
14. `numpy.isinf <#isinf>`__
15. `numpy.max <#max>`__
16. `numpy.maximum <#maximum>`__
17. `numpy.mean <#mean>`__
18. `numpy.median <#median>`__
19. `numpy.min <#min>`__
20. `numpy.minimum <#minimum>`__
21. `numpy.not_equal <#equal>`__
22. `numpy.polyfit <#polyfit>`__
23. `numpy.polyval <#polyval>`__
24. `numpy.roll <#roll>`__
25. `numpy.sort <#sort>`__
26. `numpy.std <#std>`__
27. `numpy.sum <#sum>`__
28. `numpy.trace <#trace>`__
29. `numpy.trapz <#trapz>`__
all
---
@ -399,6 +401,87 @@ and ``append`` keywords that can be found in ``numpy``.
dot
---
``numpy``:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html
**WARNING:** numpy applies upcasting rules for the multiplication of
matrices, while ``ulab`` simply returns a float matrix.
Once you can invert a matrix, you might want to know, whether the
inversion is correct. You can simply take the original matrix and its
inverse, and multiply them by calling the ``dot`` function, which takes
the two matrices as its arguments. If the matrix dimensions do not
match, the function raises a ``ValueError``. The result of the
multiplication is expected to be the unit matrix, which is demonstrated
below.
.. code::
# code to be run in micropython
from ulab import numpy as np
m = np.array([[1, 2, 3], [4, 5, 6], [7, 10, 9]], dtype=np.uint8)
n = np.linalg.inv(m)
print("m:\n", m)
print("\nm^-1:\n", n)
# this should be the unit matrix
print("\nm*m^-1:\n", np.dot(m, n))
.. parsed-literal::
m:
array([[1, 2, 3],
[4, 5, 6],
[7, 10, 9]], dtype=uint8)
m^-1:
array([[-1.25, 1.0, -0.25],
[0.4999999999999998, -1.0, 0.5],
[0.4166666666666668, 0.3333333333333333, -0.25]], dtype=float64)
m*m^-1:
array([[1.0, 0.0, 0.0],
[4.440892098500626e-16, 1.0, 0.0],
[8.881784197001252e-16, 0.0, 1.0]], dtype=float64)
Note that for matrix multiplication you dont necessarily need square
matrices, it is enough, if their dimensions are compatible (i.e., the
the left-hand-side matrix has as many columns, as does the
right-hand-side matrix rows):
.. code::
# code to be run in micropython
from ulab import numpy as np
m = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.uint8)
n = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype=np.uint8)
print(m)
print(n)
print(np.dot(m, n))
.. parsed-literal::
array([[1, 2, 3, 4],
[5, 6, 7, 8]], dtype=uint8)
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]], dtype=uint8)
array([[50.0, 60.0],
[114.0, 140.0]], dtype=float64)
equal
-----
@ -1236,6 +1319,52 @@ array. Otherwise, the calculation is along the given axis.
trace
-----
``numpy``:
https://numpy.org/doc/stable/reference/generated/numpy.trace.html
The ``trace`` function returns the sum of the diagonal elements of a
square matrix. If the input argument is not a square matrix, an
exception will be raised.
The scalar so returned will inherit the type of the input array, i.e.,
integer arrays have integer trace, and floating point arrays a floating
point trace.
.. code::
# code to be run in micropython
from ulab import numpy as np
a = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.int8)
print('a: ', a)
print('\ntrace of a: ', np.trace(a))
b = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.float)
print('='*20 + '\nb: ', b)
print('\ntrace of b: ', np.trace(b))
.. parsed-literal::
a: array([[25, 15, -5],
[15, 18, 0],
[-5, 0, 11]], dtype=int8)
trace of a: 54
====================
b: array([[25.0, 15.0, -5.0],
[15.0, 18.0, 0.0],
[-5.0, 0.0, 11.0]], dtype=float64)
trace of b: 54.0
trapz
-----

View file

@ -106,86 +106,6 @@ times are similar:
dot
---
``numpy``:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html
**WARNING:** numpy applies upcasting rules for the multiplication of
matrices, while ``ulab`` simply returns a float matrix.
Once you can invert a matrix, you might want to know, whether the
inversion is correct. You can simply take the original matrix and its
inverse, and multiply them by calling the ``dot`` function, which takes
the two matrices as its arguments. If the matrix dimensions do not
match, the function raises a ``ValueError``. The result of the
multiplication is expected to be the unit matrix, which is demonstrated
below.
.. code::
# code to be run in micropython
from ulab import numpy as np
m = np.array([[1, 2, 3], [4, 5, 6], [7, 10, 9]], dtype=np.uint8)
n = np.linalg.inv(m)
print("m:\n", m)
print("\nm^-1:\n", n)
# this should be the unit matrix
print("\nm*m^-1:\n", np.linalg.dot(m, n))
.. parsed-literal::
m:
array([[1, 2, 3],
[4, 5, 6],
[7, 10, 9]], dtype=uint8)
m^-1:
array([[-1.25, 1.0, -0.25],
[0.5, -1.0, 0.5],
[0.4166667, 0.3333334, -0.25]], dtype=float)
m*m^-1:
array([[1.0, 2.384186e-07, -1.490116e-07],
[-2.980232e-07, 1.000001, -4.172325e-07],
[-3.278255e-07, 1.311302e-06, 0.9999992]], dtype=float)
Note that for matrix multiplication you dont necessarily need square
matrices, it is enough, if their dimensions are compatible (i.e., the
the left-hand-side matrix has as many columns, as does the
right-hand-side matrix rows):
.. code::
# code to be run in micropython
from ulab import numpy as np
m = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.uint8)
n = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype=np.uint8)
print(m)
print(n)
print(np.linalg.dot(m, n))
.. parsed-literal::
array([[1, 2, 3, 4],
[5, 6, 7, 8]], dtype=uint8)
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]], dtype=uint8)
array([[7.0, 10.0],
[23.0, 34.0]], dtype=float)
eig
---
@ -398,49 +318,3 @@ The function takes a vector or matrix without options, and returns its
trace
-----
``numpy``:
https://docs.scipy.org/doc/numpy-1.17.0/reference/generated/numpy.linalg.trace.html
The ``trace`` function returns the sum of the diagonal elements of a
square matrix. If the input argument is not a square matrix, an
exception will be raised.
The scalar so returned will inherit the type of the input array, i.e.,
integer arrays have integer trace, and floating point arrays a floating
point trace.
.. code::
# code to be run in micropython
from ulab import numpy as np
a = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.int8)
print('a: ', a)
print('\ntrace of a: ', np.linalg.trace(a))
b = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.float)
print('='*20 + '\nb: ', b)
print('\ntrace of b: ', np.linalg.trace(b))
.. parsed-literal::
a: array([[25, 15, -5],
[15, 18, 0],
[-5, 0, 11]], dtype=int8)
trace of a: 54
====================
b: array([[25.0, 15.0, -5.0],
[15.0, 18.0, 0.0],
[-5.0, 0.0, 11.0]], dtype=float)
trace of b: 54.0

View file

@ -5,8 +5,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-08T16:48:29.443204Z",
"start_time": "2021-02-08T16:48:29.246310Z"
"end_time": "2021-02-13T08:28:06.727371Z",
"start_time": "2021-02-13T08:28:04.925338Z"
}
},
"outputs": [
@ -31,11 +31,11 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-08T16:48:32.087734Z",
"start_time": "2021-02-08T16:48:32.079158Z"
"end_time": "2021-02-13T08:30:08.058828Z",
"start_time": "2021-02-13T08:30:08.052317Z"
}
},
"outputs": [],
@ -49,11 +49,11 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-08T16:48:34.384905Z",
"start_time": "2021-02-08T16:48:34.333699Z"
"end_time": "2021-02-13T08:30:09.684815Z",
"start_time": "2021-02-13T08:30:09.647312Z"
}
},
"outputs": [],
@ -240,6 +240,7 @@
"1. [numpy.clip](#clip)\n",
"1. [numpy.convolve](#convolve)\n",
"1. [numpy.diff](#diff)\n",
"1. [numpy.dot](#dot)\n",
"1. [numpy.equal](#equal)\n",
"1. [numpy.flip](#flip)\n",
"1. [numpy.interp](#interp)\n",
@ -258,6 +259,7 @@
"1. [numpy.sort](#sort)\n",
"1. [numpy.std](#std)\n",
"1. [numpy.sum](#sum)\n",
"1. [numpy.trace](#trace)\n",
"1. [numpy.trapz](#trapz)"
]
},
@ -702,6 +704,112 @@
"print('\\nfirst derivative, second axis:\\n', np.diff(c, axis=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## dot\n",
"\n",
"`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html\n",
"\n",
"\n",
"**WARNING:** numpy applies upcasting rules for the multiplication of matrices, while `ulab` simply returns a float matrix. \n",
"\n",
"Once you can invert a matrix, you might want to know, whether the inversion is correct. You can simply take the original matrix and its inverse, and multiply them by calling the `dot` function, which takes the two matrices as its arguments. If the matrix dimensions do not match, the function raises a `ValueError`. The result of the multiplication is expected to be the unit matrix, which is demonstrated below."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-13T08:32:09.139378Z",
"start_time": "2021-02-13T08:32:09.122083Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"m:\n",
" array([[1, 2, 3],\n",
" [4, 5, 6],\n",
" [7, 10, 9]], dtype=uint8)\n",
"\n",
"m^-1:\n",
" array([[-1.25, 1.0, -0.25],\n",
" [0.4999999999999998, -1.0, 0.5],\n",
" [0.4166666666666668, 0.3333333333333333, -0.25]], dtype=float64)\n",
"\n",
"m*m^-1:\n",
" array([[1.0, 0.0, 0.0],\n",
" [4.440892098500626e-16, 1.0, 0.0],\n",
" [8.881784197001252e-16, 0.0, 1.0]], dtype=float64)\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"m = np.array([[1, 2, 3], [4, 5, 6], [7, 10, 9]], dtype=np.uint8)\n",
"n = np.linalg.inv(m)\n",
"print(\"m:\\n\", m)\n",
"print(\"\\nm^-1:\\n\", n)\n",
"# this should be the unit matrix\n",
"print(\"\\nm*m^-1:\\n\", np.dot(m, n))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that for matrix multiplication you don't necessarily need square matrices, it is enough, if their dimensions are compatible (i.e., the the left-hand-side matrix has as many columns, as does the right-hand-side matrix rows):"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-13T08:33:07.630825Z",
"start_time": "2021-02-13T08:33:07.608260Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"array([[1, 2, 3, 4],\n",
" [5, 6, 7, 8]], dtype=uint8)\n",
"array([[1, 2],\n",
" [3, 4],\n",
" [5, 6],\n",
" [7, 8]], dtype=uint8)\n",
"array([[50.0, 60.0],\n",
" [114.0, 140.0]], dtype=float64)\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"m = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.uint8)\n",
"n = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype=np.uint8)\n",
"print(m)\n",
"print(n)\n",
"print(np.dot(m, n))"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -1753,6 +1861,64 @@
"print('std, vertical: ', np.sum(a, axis=0))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## trace\n",
"\n",
"`numpy`: https://numpy.org/doc/stable/reference/generated/numpy.trace.html\n",
"\n",
"The `trace` function returns the sum of the diagonal elements of a square matrix. If the input argument is not a square matrix, an exception will be raised.\n",
"\n",
"The scalar so returned will inherit the type of the input array, i.e., integer arrays have integer trace, and floating point arrays a floating point trace."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-13T08:30:25.211965Z",
"start_time": "2021-02-13T08:30:25.195102Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a: array([[25, 15, -5],\n",
" [15, 18, 0],\n",
" [-5, 0, 11]], dtype=int8)\n",
"\n",
"trace of a: 54\n",
"====================\n",
"b: array([[25.0, 15.0, -5.0],\n",
" [15.0, 18.0, 0.0],\n",
" [-5.0, 0.0, 11.0]], dtype=float64)\n",
"\n",
"trace of b: 54.0\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"a = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.int8)\n",
"print('a: ', a)\n",
"print('\\ntrace of a: ', np.trace(a))\n",
"\n",
"b = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.float)\n",
"\n",
"print('='*20 + '\\nb: ', b)\n",
"print('\\ntrace of b: ', np.trace(b))"
]
},
{
"cell_type": "markdown",
"metadata": {},

View file

@ -371,111 +371,6 @@
"matrix_det(m)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## dot\n",
"\n",
"`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html\n",
"\n",
"\n",
"**WARNING:** numpy applies upcasting rules for the multiplication of matrices, while `ulab` simply returns a float matrix. \n",
"\n",
"Once you can invert a matrix, you might want to know, whether the inversion is correct. You can simply take the original matrix and its inverse, and multiply them by calling the `dot` function, which takes the two matrices as its arguments. If the matrix dimensions do not match, the function raises a `ValueError`. The result of the multiplication is expected to be the unit matrix, which is demonstrated below."
]
},
{
"cell_type": "code",
"execution_count": 556,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-20T07:13:30.102776Z",
"start_time": "2019-10-20T07:13:30.073704Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"m:\n",
" array([[1, 2, 3],\n",
"\t [4, 5, 6],\n",
"\t [7, 10, 9]], dtype=uint8)\n",
"\n",
"m^-1:\n",
" array([[-1.25, 1.0, -0.25],\n",
"\t [0.5, -1.0, 0.5],\n",
"\t [0.4166667, 0.3333334, -0.25]], dtype=float)\n",
"\n",
"m*m^-1:\n",
" array([[1.0, 2.384186e-07, -1.490116e-07],\n",
"\t [-2.980232e-07, 1.000001, -4.172325e-07],\n",
"\t [-3.278255e-07, 1.311302e-06, 0.9999992]], dtype=float)\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"m = np.array([[1, 2, 3], [4, 5, 6], [7, 10, 9]], dtype=np.uint8)\n",
"n = np.linalg.inv(m)\n",
"print(\"m:\\n\", m)\n",
"print(\"\\nm^-1:\\n\", n)\n",
"# this should be the unit matrix\n",
"print(\"\\nm*m^-1:\\n\", np.linalg.dot(m, n))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that for matrix multiplication you don't necessarily need square matrices, it is enough, if their dimensions are compatible (i.e., the the left-hand-side matrix has as many columns, as does the right-hand-side matrix rows):"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"ExecuteTime": {
"end_time": "2019-10-10T17:33:17.921324Z",
"start_time": "2019-10-10T17:33:17.900587Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"array([[1, 2, 3, 4],\n",
"\t [5, 6, 7, 8]], dtype=uint8)\n",
"array([[1, 2],\n",
"\t [3, 4],\n",
"\t [5, 6],\n",
"\t [7, 8]], dtype=uint8)\n",
"array([[7.0, 10.0],\n",
"\t [23.0, 34.0]], dtype=float)\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"m = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=np.uint8)\n",
"n = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype=np.uint8)\n",
"print(m)\n",
"print(n)\n",
"print(np.linalg.dot(m, n))"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -770,59 +665,6 @@
"print('norm of a:', np.linalg.norm(a))\n",
"print('norm of b:', np.linalg.norm(b))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## trace\n",
"\n",
"`numpy`: https://docs.scipy.org/doc/numpy-1.17.0/reference/generated/numpy.linalg.trace.html\n",
"\n",
"The `trace` function returns the sum of the diagonal elements of a square matrix. If the input argument is not a square matrix, an exception will be raised.\n",
"\n",
"The scalar so returned will inherit the type of the input array, i.e., integer arrays have integer trace, and floating point arrays a floating point trace."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a: array([[25, 15, -5],\n",
"\t [15, 18, 0],\n",
"\t [-5, 0, 11]], dtype=int8)\n",
"\n",
"trace of a: 54\n",
"====================\n",
"b: array([[25.0, 15.0, -5.0],\n",
"\t [15.0, 18.0, 0.0],\n",
"\t [-5.0, 0.0, 11.0]], dtype=float)\n",
"\n",
"trace of b: 54.0\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"a = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.int8)\n",
"print('a: ', a)\n",
"print('\\ntrace of a: ', np.linalg.trace(a))\n",
"\n",
"b = np.array([[25, 15, -5], [15, 18, 0], [-5, 0, 11]], dtype=np.float)\n",
"\n",
"print('='*20 + '\\nb: ', b)\n",
"print('\\ntrace of b: ', np.linalg.trace(b))"
]
}
],
"metadata": {

View file

@ -4,6 +4,12 @@ version 2.4.0
added byteswap method
Sun, 14 Feb 2021
version 2.3.7
fixed frombuffer implementation glitch
Wed, 10 Feb 2021
version 2.3.5

View file

@ -17,8 +17,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-08T16:56:25.845993Z",
"start_time": "2021-02-08T16:56:25.830627Z"
"end_time": "2021-02-13T08:27:23.976552Z",
"start_time": "2021-02-13T08:27:23.964444Z"
}
},
"outputs": [
@ -61,7 +61,7 @@
"author = 'Zoltán Vörös'\n",
"\n",
"# The full version, including alpha/beta/rc tags\n",
"release = '2.3.0'\n",
"release = '2.3.6'\n",
"\n",
"\n",
"# -- General configuration ---------------------------------------------------\n",
@ -215,8 +215,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-08T16:56:31.525356Z",
"start_time": "2021-02-08T16:56:31.354760Z"
"end_time": "2021-02-13T08:35:30.625437Z",
"start_time": "2021-02-13T08:35:28.173618Z"
}
},
"outputs": [],
@ -256,8 +256,8 @@
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2021-02-08T16:57:02.367061Z",
"start_time": "2021-02-08T16:56:57.710745Z"
"end_time": "2021-02-13T08:35:36.916035Z",
"start_time": "2021-02-13T08:35:32.271138Z"
}
},
"outputs": [],

View file

@ -5,41 +5,9 @@ try:
except ImportError:
import numpy as np
use_ulab = False
if use_ulab:
a = np.array([1,2,3], dtype=np.int16)
b = np.array([4,5,6], dtype=np.int16)
ab = np.linalg.dot(a.transpose(), b)
print(math.isclose(ab, 32.0, rel_tol=1E-9, abs_tol=1E-9))
a = np.array([1,2,3], dtype=np.int16)
b = np.array([4,5,6], dtype=np.float)
ab = np.linalg.dot(a.transpose(), b)
print(math.isclose(ab, 32.0, rel_tol=1E-9, abs_tol=1E-9))
a = np.array([[1., 2.], [3., 4.]])
b = np.linalg.inv(a)
ab = np.linalg.dot(a, b)
m,n = ab.shape()
for i in range(m):
for j in range(n):
if i == j:
print(math.isclose(ab[i][j], 1.0, rel_tol=1E-9, abs_tol=1E-9))
else:
print(math.isclose(ab[i][j], 0.0, rel_tol=1E-9, abs_tol=1E-9))
a = np.array([[1, 2, 3, 4], [4, 5, 6, 4], [7, 8.6, 9, 4], [3, 4, 5, 6]])
b = np.linalg.inv(a)
ab = np.linalg.dot(a, b)
m,n = ab.shape()
for i in range(m):
for j in range(n):
if i == j:
print(math.isclose(ab[i][j], 1.0, rel_tol=1E-9, abs_tol=1E-9))
else:
print(math.isclose(ab[i][j], 0.0, rel_tol=1E-9, abs_tol=1E-9))
else:
a = np.array([1,2,3], dtype=np.int16)
b = np.array([4,5,6], dtype=np.int16)
ab = np.dot(a.transpose(), b)
@ -49,11 +17,14 @@ else:
b = np.array([4,5,6], dtype=np.float)
ab = np.dot(a.transpose(), b)
print(math.isclose(ab, 32.0, rel_tol=1E-9, abs_tol=1E-9))
a = np.array([[1., 2.], [3., 4.]])
b = np.linalg.inv(a)
ab = np.dot(a, b)
m,n = ab.shape
if use_ulab:
m, n = ab.shape()
else:
m, n = ab.shape
for i in range(m):
for j in range(n):
if i == j:
@ -64,16 +35,19 @@ else:
a = np.array([[1, 2, 3, 4], [4, 5, 6, 4], [7, 8.6, 9, 4], [3, 4, 5, 6]])
b = np.linalg.inv(a)
ab = np.dot(a, b)
m,n = ab.shape
if use_ulab:
m, n = ab.shape()
else:
m, n = ab.shape
for i in range(m):
for j in range(n):
if i == j:
print(math.isclose(ab[i][j], 1.0, rel_tol=1E-9, abs_tol=1E-9))
else:
print(math.isclose(ab[i][j], 0.0, rel_tol=1E-9, abs_tol=1E-9))
a = np.array([[1, 2, 3, 4], [4, 5, 6, 4], [7, 8.6, 9, 4], [3, 4, 5, 6]])
result = (np.linalg.det(a))
result = (np.linalg.det(a))
ref_result = 7.199999999999995
print(math.isclose(result, ref_result, rel_tol=1E-9, abs_tol=1E-9))
@ -107,19 +81,13 @@ ref_result = 16.881943016134134
print(math.isclose(result, ref_result, rel_tol=1E-6, abs_tol=1E-6))
a = np.array([[0, 1, 2], [3, 4 ,5], [5, 4, 8], [4, 4, 8] ], dtype=np.int16)
result = (np.linalg.norm(a,axis=0)) # fails on low tolerance
result = (np.linalg.norm(a,axis=0)) # fails on low tolerance
ref_result = np.array([7.071068, 7.0, 12.52996])
for i in range(3):
print(math.isclose(result[i], ref_result[i], rel_tol=1E-6, abs_tol=1E-6))
a = np.array([[0, 1, 2], [3, 4 ,5], [5, 4, 8], [4, 4, 8] ], dtype=np.int16)
result = (np.linalg.norm(a,axis=1)) # fails on low tolerance
result = (np.linalg.norm(a,axis=1)) # fails on low tolerance
ref_result = np.array([2.236068, 7.071068, 10.24695, 9.797959])
for i in range(4):
print(math.isclose(result[i], ref_result[i], rel_tol=1E-6, abs_tol=1E-6))
if use_ulab:
print(np.linalg.trace(np.eye(3)))
else:
print(np.trace(np.eye(3)))

View file

@ -51,4 +51,3 @@ True
True
True
True
3.0