From 03d48f07dd99cf16d737db7f49c4ad23f8bcc349 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Sat, 30 Jul 2022 23:19:57 +0900 Subject: [PATCH 1/8] Filling out template with PR 1839 --- proposals/p1839.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 proposals/p1839.md diff --git a/proposals/p1839.md b/proposals/p1839.md new file mode 100644 index 0000000000000..90b94a491be2a --- /dev/null +++ b/proposals/p1839.md @@ -0,0 +1,64 @@ +# Multidimensional array + + + +[Pull request](https://github.com/carbon-language/carbon-lang/pull/1839) + + + +## Table of contents + +- [Problem](#problem) +- [Background](#background) +- [Proposal](#proposal) +- [Details](#details) +- [Rationale](#rationale) +- [Alternatives considered](#alternatives-considered) + + + +## Problem + +TODO: What problem are you trying to solve? How important is that problem? Who +is impacted by it? + +## Background + +TODO: Is there any background that readers should consider to fully understand +this problem and your approach to solving it? + +## Proposal + +TODO: Briefly and at a high level, how do you propose to solve the problem? Why +will that in fact solve it? + +## Details + +TODO: Fully explain the details of the proposed solution. + +## Rationale + +TODO: How does this proposal effectively advance Carbon's goals? Rather than +re-stating the full motivation, this should connect that motivation back to +Carbon's stated goals and principles. This may evolve during review. Use links +to appropriate sections of [`/docs/project/goals.md`](/docs/project/goals.md), +and/or to documents in [`/docs/project/principles`](/docs/project/principles). +For example: + +- [Community and culture](/docs/project/goals.md#community-and-culture) +- [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem) +- [Performance-critical software](/docs/project/goals.md#performance-critical-software) +- [Software and language evolution](/docs/project/goals.md#software-and-language-evolution) +- [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write) +- [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms) +- [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development) +- [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments) +- [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code) + +## Alternatives considered + +TODO: What alternative solutions have you considered? From aa1dfb9278d9919eb5b5fa75ae1e4145c9c7002b Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Sat, 30 Jul 2022 23:24:54 +0900 Subject: [PATCH 2/8] Multidimensional array proposal --- proposals/p1839.md | 315 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 291 insertions(+), 24 deletions(-) diff --git a/proposals/p1839.md b/proposals/p1839.md index 90b94a491be2a..93a0305059f78 100644 --- a/proposals/p1839.md +++ b/proposals/p1839.md @@ -23,42 +23,309 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ## Problem -TODO: What problem are you trying to solve? How important is that problem? Who -is impacted by it? +Multidimensional arrays are actively used in numerical methods, machine +intelligence and data science. This is one feature than makes modern Fortran +more attractive than C++ when it comes to a choice of compiled language: +currently, C++ lacks support of multidimensional arrays. Having Carbon implement +this would give it a major boost in the eyes of the scientific community. + +Nested arrays may look as a good alternative of multidimensional arrays but +their performance may be not effective due to splitting in memory. ## Background -TODO: Is there any background that readers should consider to fully understand -this problem and your approach to solving it? +Multidimensional array is an array with more than two dimensions which is +continuous in memory. + +Multidimensional array may be stored in memory in +[row- or column- major order](https://en.wikipedia.org/wiki/Row-_and_column-major_order). ## Proposal -TODO: Briefly and at a high level, how do you propose to solve the problem? Why -will that in fact solve it? +We should add support of multidimensional arrays in Carbon via syntax extension +for making code clean and simplier for reading and writing. + +```carbon + var A: [f64; 3; 4]; + var values: i64 = 0; + for(Ai: auto in A[:,...]) { + for(Aij: auto in Ai[:,...]) { + Aij = values++; + } } +``` +or +```carbon + var A: [f64; 3; 4]; + var values: i64 = 0; + for(i: auto in (0:2)) { + for(j: auto in (0:3)) { + A[i,j] = values++; + } } +``` ## Details -TODO: Fully explain the details of the proposed solution. +### Definition + +Define an array 3x2 with explicit dimensions: +```carbon + var x: [i32; 3; 2] = ((0, 1, 2), (3, 4, 5)); +``` +For avoiding explicit difinition of array dimensions, use `:`: +```carbon + var x: [i32; :; :] = ((0, 1, 2), (3, 4, 5)); +``` + +#### Automatic allocation + +Arrays can be automatically allocated: +```carbon + var x: [i32; :, :]; +``` +For avoiding Undefined Behavior, `x` has shape `(0, 0)`. + +Array may be defined: +1. via **assignment**: + ```carbon + var x: [i32; :, :]; + var y: [i32; :, :] = ((0, 1, 2), (3, 4, 5)); + x = y; + ``` +2. via **memory allocation**: + ```carbon + var x: [i32; :, :]; + allocate(x, /*shape=*/(3, 2)); + ``` + +If array was already allocated and then, `allocate` called, the runtime error is. + +#### Automatic deallocation + +Automatically allocated arrays are destroying at the end of scope. For example, +if such arrays belong to class object, they are destroying with class object. + +Manually, deallocation can be called using: +```carbon + var x: [i32; :, :]; + allocate(x, /*shape=*/(3, 2)); + deallocate(x); +``` +Calling of deallocation for non-allocated arrays leads to runtime error. + +### Operators + +Arrays may be modified in scalar and vector ways. + +1. Scalar way: + ```carbon + var x: [i32; 3; 2] = ((0, 1, 2), (3, 4, 5)); + var y: auto = -x; + // each to each elements are summarized + var z: auto = x + y; // z = ((0,0,0), (0,0,0)) + ``` + If shapes are inconsistent, runtime error is. + +2. Vector way: + ```carbon + var x: [i32; 3; 2] = ((0, 1, 2), (3, 4, 5)); + // multiply each element by 2 + x *= 2; // x = ((0, 2, 4), (6, 8, 10)); + ``` + +### Slices and indexes + +Array slices (or sections) has the following syntax: +```carbon + var x: [i32; 3; 2] = ((0, 1, 2), (3, 4, 5)); + var z: auto = x[:, 1]; // z = (3, 4, 5) +``` + +Slice syntax: `a:b:s`. Here, `a` is the begin of slice, `b` is the end of slice +and `s` is the step in slice. `:s` can be omitted, then it means that step is 1. +If `a` is omitted, slice starts from the beginning of array. The same situation +is for `b`, but slice ends at the end of arrays. `:` is the same as `::`. + +If array is inside indexes, it uses array values as indexes: +```carbon + var ind: [i32; :] = (0, 1, 1, 2, 2); + var x: [i32; :] = (3, 5, 7); + var y: auto = x[ind]; // y = (3, 5, 5, 7, 7) +``` + +Slices can be also in left-hand side: +```carbon + var x: [i32; 3; 2] = ((0, 1, 2), (3, 4, 5)); + x[:, 0] = x[:, 1]; // x = ((3, 4, 5), (3, 4, 5)); +``` + +### Iterators (?) + +In multidimensional arrays, it may be useful to have _iterators_ (row-major +order): +```carbon + var A: [f64; 2; 3; 4]; + var it: auto = A[:, ...]; + for(i: auto in it) { ... } +``` +In this example, `i` presents `A[0,:,:]` and `A[1,:,:]` sequentially. +Also, iterator may use last dimension (column-major order): +```carbon + var A: [f64; 4; 3; 2]; + var it: auto = A[..., :]; + for(i: auto in it) { ... } +``` +In this example, `i` presents `A[:,:,0]` and `A[:,:,1]` sequentially. +In both cases, `i` is two dimensional array. + +`...` masks all dimensions. + +### Array generators + +Slice syntax can be used for constructing arrays: +```carbon + var x: [i32; 3; 2] = ((0:4:2), (5:3:-1)); + var y: [i32; 3; 2] = ((0, 2, 4), (5, 4, 3)); +``` +Here, `x` and `y` have the same values. + +### Functions + +Usually, arrays uses as is. Below, sum of two arrays is: +```carbon + fn sum[T:! Type](x: T, y: T) -> T { + return x + y; + } +``` + +Function returning 1D array: +```carbon + fn arr1D[T:! Type](x: T, y: T) -> T[:] { + return (x, y); + } +``` +or 2D array: +```carbon + fn arr2D[T:! Type](x: T, y: T) -> T[:,:] { + return ((x, x), (y, y)); + } +``` + +Dimensions may be specified explicitly: +```carbon + fn arr1D[T:! Type](x: T, y: T) -> T[2] { + return (x, y); + } +``` + +Lowering dimensions: +```carbon + fn unarr[T:! Type](x: T[:], y: T[:]) -> T { + return sum(x + y); + } +``` + +#### Elemental functions + +These functions applied to each element sequentially. + +```carbon + el fn inc[T:! Type](x: T) -> T { + return x + 1; + } +fn Main() -> i32 { + var x: [i32, 3] = (0:2); + var y: i32 = 3; + x = inc(x); // similar to x = x + 1; + y = inc(y); + return 0; +} +``` +It is useful when function is more compilicated than increment. + +Using _iterators_, elemental function may be used for sub-dimensions: +```carbon +el fn conv[T:! Type](x: T) -> T { + return sum(x); +} +fn Main() -> i32 { + var x: [i32, 3, 4] = reshape((0:11),/*shape=*/(3, 4)); + var y: auto = conv(x[:,...]); // y = (6, 22, 38) + var z: auto = conv(x[...,:]); // z = (12, 15, 18, 21) + return 0; +} +``` + +### Standard library + +#### allocate +Allocates array: + ```carbon + var x: [i32; :, :]; + allocate(x, /*shape=*/(3, 2)); + ``` +#### deallocate +Deallocates array: + ```carbon + var x: [i32; :, :]; + allocate(x, /*shape=*/(3, 2)); + deallocate(x); + ``` +#### allocated +Returns status of allocation: + ```carbon + var x: [i32; :, :]; + allocated(x); // False + allocate(x, /*shape=*/(3, 2)); + allocated(x); // True + deallocate(x); + allocated(x); // False + ``` +#### shape +Returns shape of arrays: +```carbon + var s: [i32; 2] = shape(x); // s = (3, 2) +``` +#### size +Returns total array size: +```carbon + var l: i32 = size(x); // l = 6 +``` +With optional argument `dim` returns size in given dimension (indexing from 1): +```carbon + var l1: i32 = size(x, /*dim=*/1); // l1 = 3 + var l2: i32 = size(x, /*dim=*/2); // l2 = 2 +``` +#### reshape +Reshapes array: +```carbon + var x: [i32; 3; 2] = reshape(/*array=*/(0, 1, 2, 3, 4, 5), /*shape=*/(3, 2));/ +``` +#### transpose +Transposes array (without additional argument only for 2D): +```carbon + var x: [i32; 3; 2] = ((0, 1, 2), (3, 4, 5)); + var y: auto = transpose(x); // y = ((0, 3), (1, 4), (2, 5)) + var z: auto = shape(y); // z = (2, 3) +``` +Additional argument `dims` marks dimensions for transposing: +```carbon + var x: [i32; 2; 2; 2] = ( ((0, 1), (2, 3)), ((4, 5), (6, 7)) ); + var y: auto = transpose(x, /*dims=*/(1, 3)); + // y = ( ((0, 4), (2, 6)), ((1, 5), (3, 7)) ) +``` +#### sum +Sums all values in array: +```carbon + var x: [i32; 2; 2; 2] = ( ((0, 1), (2, 3)), ((4, 5), (6, 7)) ); + var y: auto = sum(x); // y = 28 +``` ## Rationale -TODO: How does this proposal effectively advance Carbon's goals? Rather than -re-stating the full motivation, this should connect that motivation back to -Carbon's stated goals and principles. This may evolve during review. Use links -to appropriate sections of [`/docs/project/goals.md`](/docs/project/goals.md), -and/or to documents in [`/docs/project/principles`](/docs/project/principles). -For example: - -- [Community and culture](/docs/project/goals.md#community-and-culture) -- [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem) -- [Performance-critical software](/docs/project/goals.md#performance-critical-software) -- [Software and language evolution](/docs/project/goals.md#software-and-language-evolution) -- [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write) -- [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms) -- [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development) -- [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments) -- [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code) +This proposal should simplify to write High-Performance Compiting codes, +most of them is performance-critical software. Unfortunately, C++ code is not +affected. ## Alternatives considered -TODO: What alternative solutions have you considered? +I'm under high impress of Fortran. From 76ff705810cbb5c2c001d722fa24fc495ed98ccd Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Sun, 31 Jul 2022 00:36:23 +0900 Subject: [PATCH 3/8] Fix proposal name --- proposals/p1839.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/p1839.md b/proposals/p1839.md index 93a0305059f78..a266cd596a933 100644 --- a/proposals/p1839.md +++ b/proposals/p1839.md @@ -1,4 +1,4 @@ -# Multidimensional array +# Multidimensional arrays