164ab3302SCarolineConcatto //===-- lib/Evaluate/constant.cpp -----------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto
964ab3302SCarolineConcatto #include "flang/Evaluate/constant.h"
1064ab3302SCarolineConcatto #include "flang/Evaluate/expression.h"
1164ab3302SCarolineConcatto #include "flang/Evaluate/shape.h"
1264ab3302SCarolineConcatto #include "flang/Evaluate/type.h"
1364ab3302SCarolineConcatto #include <string>
1464ab3302SCarolineConcatto
1564ab3302SCarolineConcatto namespace Fortran::evaluate {
1664ab3302SCarolineConcatto
ConstantBounds(const ConstantSubscripts & shape)1764ab3302SCarolineConcatto ConstantBounds::ConstantBounds(const ConstantSubscripts &shape)
1864ab3302SCarolineConcatto : shape_(shape), lbounds_(shape_.size(), 1) {}
1964ab3302SCarolineConcatto
ConstantBounds(ConstantSubscripts && shape)2064ab3302SCarolineConcatto ConstantBounds::ConstantBounds(ConstantSubscripts &&shape)
2164ab3302SCarolineConcatto : shape_(std::move(shape)), lbounds_(shape_.size(), 1) {}
2264ab3302SCarolineConcatto
2364ab3302SCarolineConcatto ConstantBounds::~ConstantBounds() = default;
2464ab3302SCarolineConcatto
set_lbounds(ConstantSubscripts && lb)2564ab3302SCarolineConcatto void ConstantBounds::set_lbounds(ConstantSubscripts &&lb) {
2664ab3302SCarolineConcatto CHECK(lb.size() == shape_.size());
2764ab3302SCarolineConcatto lbounds_ = std::move(lb);
283b61587cSPeter Klausler for (std::size_t j{0}; j < shape_.size(); ++j) {
293b61587cSPeter Klausler if (shape_[j] == 0) {
303b61587cSPeter Klausler lbounds_[j] = 1;
313b61587cSPeter Klausler }
323b61587cSPeter Klausler }
3364ab3302SCarolineConcatto }
3464ab3302SCarolineConcatto
ComputeUbounds(std::optional<int> dim) const35d8b4ea48SMike Kashkarov ConstantSubscripts ConstantBounds::ComputeUbounds(
36d8b4ea48SMike Kashkarov std::optional<int> dim) const {
37d8b4ea48SMike Kashkarov if (dim) {
38d8b4ea48SMike Kashkarov CHECK(*dim < Rank());
39c3859818SLeandro Lupori return {lbounds_[*dim] + (shape_[*dim] - 1)};
40d8b4ea48SMike Kashkarov } else {
41d8b4ea48SMike Kashkarov ConstantSubscripts ubounds(Rank());
42d8b4ea48SMike Kashkarov for (int i{0}; i < Rank(); ++i) {
43c3859818SLeandro Lupori ubounds[i] = lbounds_[i] + (shape_[i] - 1);
44d8b4ea48SMike Kashkarov }
45d8b4ea48SMike Kashkarov return ubounds;
46d8b4ea48SMike Kashkarov }
47d8b4ea48SMike Kashkarov }
48d8b4ea48SMike Kashkarov
SetLowerBoundsToOne()4982568675SPeter Klausler void ConstantBounds::SetLowerBoundsToOne() {
5082568675SPeter Klausler for (auto &n : lbounds_) {
5182568675SPeter Klausler n = 1;
5282568675SPeter Klausler }
5382568675SPeter Klausler }
5482568675SPeter Klausler
SHAPE() const5564ab3302SCarolineConcatto Constant<SubscriptInteger> ConstantBounds::SHAPE() const {
5664ab3302SCarolineConcatto return AsConstantShape(shape_);
5764ab3302SCarolineConcatto }
5864ab3302SCarolineConcatto
HasNonDefaultLowerBound() const5916c4b320SPeter Klausler bool ConstantBounds::HasNonDefaultLowerBound() const {
6016c4b320SPeter Klausler for (auto n : lbounds_) {
6116c4b320SPeter Klausler if (n != 1) {
6216c4b320SPeter Klausler return true;
6316c4b320SPeter Klausler }
6416c4b320SPeter Klausler }
6516c4b320SPeter Klausler return false;
6616c4b320SPeter Klausler }
6716c4b320SPeter Klausler
SubscriptsToOffset(const ConstantSubscripts & index) const6864ab3302SCarolineConcatto ConstantSubscript ConstantBounds::SubscriptsToOffset(
6964ab3302SCarolineConcatto const ConstantSubscripts &index) const {
7064ab3302SCarolineConcatto CHECK(GetRank(index) == GetRank(shape_));
7164ab3302SCarolineConcatto ConstantSubscript stride{1}, offset{0};
7264ab3302SCarolineConcatto int dim{0};
7364ab3302SCarolineConcatto for (auto j : index) {
7464ab3302SCarolineConcatto auto lb{lbounds_[dim]};
7564ab3302SCarolineConcatto auto extent{shape_[dim++]};
76c3859818SLeandro Lupori CHECK(j >= lb && j - lb < extent);
7764ab3302SCarolineConcatto offset += stride * (j - lb);
7864ab3302SCarolineConcatto stride *= extent;
7964ab3302SCarolineConcatto }
8064ab3302SCarolineConcatto return offset;
8164ab3302SCarolineConcatto }
8264ab3302SCarolineConcatto
TotalElementCount(const ConstantSubscripts & shape)837358c26dSLeandro Lupori std::optional<uint64_t> TotalElementCount(const ConstantSubscripts &shape) {
847358c26dSLeandro Lupori uint64_t size{1};
857358c26dSLeandro Lupori for (auto dim : shape) {
867358c26dSLeandro Lupori CHECK(dim >= 0);
877358c26dSLeandro Lupori uint64_t osize{size};
887358c26dSLeandro Lupori size = osize * dim;
897358c26dSLeandro Lupori if (size > std::numeric_limits<decltype(dim)>::max() ||
907358c26dSLeandro Lupori (dim != 0 && size / dim != osize)) {
917358c26dSLeandro Lupori return std::nullopt;
927358c26dSLeandro Lupori }
937358c26dSLeandro Lupori }
947358c26dSLeandro Lupori return static_cast<uint64_t>(GetSize(shape));
9582568675SPeter Klausler }
9682568675SPeter Klausler
IncrementSubscripts(ConstantSubscripts & indices,const std::vector<int> * dimOrder) const9764ab3302SCarolineConcatto bool ConstantBounds::IncrementSubscripts(
9864ab3302SCarolineConcatto ConstantSubscripts &indices, const std::vector<int> *dimOrder) const {
9964ab3302SCarolineConcatto int rank{GetRank(shape_)};
10064ab3302SCarolineConcatto CHECK(GetRank(indices) == rank);
10164ab3302SCarolineConcatto CHECK(!dimOrder || static_cast<int>(dimOrder->size()) == rank);
10264ab3302SCarolineConcatto for (int j{0}; j < rank; ++j) {
10364ab3302SCarolineConcatto ConstantSubscript k{dimOrder ? (*dimOrder)[j] : j};
10464ab3302SCarolineConcatto auto lb{lbounds_[k]};
10564ab3302SCarolineConcatto CHECK(indices[k] >= lb);
106c3859818SLeandro Lupori if (++indices[k] - lb < shape_[k]) {
10764ab3302SCarolineConcatto return true;
10864ab3302SCarolineConcatto } else {
109c3859818SLeandro Lupori CHECK(indices[k] - lb == std::max<ConstantSubscript>(shape_[k], 1));
11064ab3302SCarolineConcatto indices[k] = lb;
11164ab3302SCarolineConcatto }
11264ab3302SCarolineConcatto }
11364ab3302SCarolineConcatto return false; // all done
11464ab3302SCarolineConcatto }
11564ab3302SCarolineConcatto
ValidateDimensionOrder(int rank,const std::vector<int> & order)11664ab3302SCarolineConcatto std::optional<std::vector<int>> ValidateDimensionOrder(
11764ab3302SCarolineConcatto int rank, const std::vector<int> &order) {
11864ab3302SCarolineConcatto std::vector<int> dimOrder(rank);
11964ab3302SCarolineConcatto if (static_cast<int>(order.size()) == rank) {
12064ab3302SCarolineConcatto std::bitset<common::maxRank> seenDimensions;
12164ab3302SCarolineConcatto for (int j{0}; j < rank; ++j) {
12264ab3302SCarolineConcatto int dim{order[j]};
12364ab3302SCarolineConcatto if (dim < 1 || dim > rank || seenDimensions.test(dim - 1)) {
12464ab3302SCarolineConcatto return std::nullopt;
12564ab3302SCarolineConcatto }
12685ec4493SPeter Klausler dimOrder[j] = dim - 1;
12764ab3302SCarolineConcatto seenDimensions.set(dim - 1);
12864ab3302SCarolineConcatto }
12964ab3302SCarolineConcatto return dimOrder;
13064ab3302SCarolineConcatto } else {
13164ab3302SCarolineConcatto return std::nullopt;
13264ab3302SCarolineConcatto }
13364ab3302SCarolineConcatto }
13464ab3302SCarolineConcatto
HasNegativeExtent(const ConstantSubscripts & shape)1352cf52504SPeter Steinfeld bool HasNegativeExtent(const ConstantSubscripts &shape) {
13664ab3302SCarolineConcatto for (ConstantSubscript extent : shape) {
13764ab3302SCarolineConcatto if (extent < 0) {
1382cf52504SPeter Steinfeld return true;
1392cf52504SPeter Steinfeld }
1402cf52504SPeter Steinfeld }
14164ab3302SCarolineConcatto return false;
14264ab3302SCarolineConcatto }
14364ab3302SCarolineConcatto
14464ab3302SCarolineConcatto template <typename RESULT, typename ELEMENT>
ConstantBase(std::vector<Element> && x,ConstantSubscripts && sh,Result res)14564ab3302SCarolineConcatto ConstantBase<RESULT, ELEMENT>::ConstantBase(
14664ab3302SCarolineConcatto std::vector<Element> &&x, ConstantSubscripts &&sh, Result res)
14764ab3302SCarolineConcatto : ConstantBounds(std::move(sh)), result_{res}, values_(std::move(x)) {
1487358c26dSLeandro Lupori CHECK(TotalElementCount(shape()) && size() == *TotalElementCount(shape()));
14964ab3302SCarolineConcatto }
15064ab3302SCarolineConcatto
15164ab3302SCarolineConcatto template <typename RESULT, typename ELEMENT>
~ConstantBase()15264ab3302SCarolineConcatto ConstantBase<RESULT, ELEMENT>::~ConstantBase() {}
15364ab3302SCarolineConcatto
15464ab3302SCarolineConcatto template <typename RESULT, typename ELEMENT>
operator ==(const ConstantBase & that) const15564ab3302SCarolineConcatto bool ConstantBase<RESULT, ELEMENT>::operator==(const ConstantBase &that) const {
15664ab3302SCarolineConcatto return shape() == that.shape() && values_ == that.values_;
15764ab3302SCarolineConcatto }
15864ab3302SCarolineConcatto
15964ab3302SCarolineConcatto template <typename RESULT, typename ELEMENT>
Reshape(const ConstantSubscripts & dims) const16064ab3302SCarolineConcatto auto ConstantBase<RESULT, ELEMENT>::Reshape(
16164ab3302SCarolineConcatto const ConstantSubscripts &dims) const -> std::vector<Element> {
1627358c26dSLeandro Lupori std::optional<uint64_t> optN{TotalElementCount(dims)};
163*a51d13f5SCarlos Seo CHECK_MSG(optN, "Overflow in TotalElementCount");
1647358c26dSLeandro Lupori uint64_t n{*optN};
16564ab3302SCarolineConcatto CHECK(!empty() || n == 0);
16664ab3302SCarolineConcatto std::vector<Element> elements;
16764ab3302SCarolineConcatto auto iter{values().cbegin()};
16864ab3302SCarolineConcatto while (n-- > 0) {
16964ab3302SCarolineConcatto elements.push_back(*iter);
17064ab3302SCarolineConcatto if (++iter == values().cend()) {
17164ab3302SCarolineConcatto iter = values().cbegin();
17264ab3302SCarolineConcatto }
17364ab3302SCarolineConcatto }
17464ab3302SCarolineConcatto return elements;
17564ab3302SCarolineConcatto }
17664ab3302SCarolineConcatto
17764ab3302SCarolineConcatto template <typename RESULT, typename ELEMENT>
CopyFrom(const ConstantBase<RESULT,ELEMENT> & source,std::size_t count,ConstantSubscripts & resultSubscripts,const std::vector<int> * dimOrder)17864ab3302SCarolineConcatto std::size_t ConstantBase<RESULT, ELEMENT>::CopyFrom(
17964ab3302SCarolineConcatto const ConstantBase<RESULT, ELEMENT> &source, std::size_t count,
18064ab3302SCarolineConcatto ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) {
18164ab3302SCarolineConcatto std::size_t copied{0};
18264ab3302SCarolineConcatto ConstantSubscripts sourceSubscripts{source.lbounds()};
18364ab3302SCarolineConcatto while (copied < count) {
18464ab3302SCarolineConcatto values_.at(SubscriptsToOffset(resultSubscripts)) =
18564ab3302SCarolineConcatto source.values_.at(source.SubscriptsToOffset(sourceSubscripts));
18664ab3302SCarolineConcatto copied++;
18764ab3302SCarolineConcatto source.IncrementSubscripts(sourceSubscripts);
18864ab3302SCarolineConcatto IncrementSubscripts(resultSubscripts, dimOrder);
18964ab3302SCarolineConcatto }
19064ab3302SCarolineConcatto return copied;
19164ab3302SCarolineConcatto }
19264ab3302SCarolineConcatto
19364ab3302SCarolineConcatto template <typename T>
At(const ConstantSubscripts & index) const19464ab3302SCarolineConcatto auto Constant<T>::At(const ConstantSubscripts &index) const -> Element {
19564ab3302SCarolineConcatto return Base::values_.at(Base::SubscriptsToOffset(index));
19664ab3302SCarolineConcatto }
19764ab3302SCarolineConcatto
19864ab3302SCarolineConcatto template <typename T>
Reshape(ConstantSubscripts && dims) const19964ab3302SCarolineConcatto auto Constant<T>::Reshape(ConstantSubscripts &&dims) const -> Constant {
20064ab3302SCarolineConcatto return {Base::Reshape(dims), std::move(dims)};
20164ab3302SCarolineConcatto }
20264ab3302SCarolineConcatto
20364ab3302SCarolineConcatto template <typename T>
CopyFrom(const Constant<T> & source,std::size_t count,ConstantSubscripts & resultSubscripts,const std::vector<int> * dimOrder)20464ab3302SCarolineConcatto std::size_t Constant<T>::CopyFrom(const Constant<T> &source, std::size_t count,
20564ab3302SCarolineConcatto ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) {
20664ab3302SCarolineConcatto return Base::CopyFrom(source, count, resultSubscripts, dimOrder);
20764ab3302SCarolineConcatto }
20864ab3302SCarolineConcatto
20964ab3302SCarolineConcatto // Constant<Type<TypeCategory::Character, KIND> specializations
21064ab3302SCarolineConcatto template <int KIND>
Constant(const Scalar<Result> & str)21164ab3302SCarolineConcatto Constant<Type<TypeCategory::Character, KIND>>::Constant(
21264ab3302SCarolineConcatto const Scalar<Result> &str)
21364ab3302SCarolineConcatto : values_{str}, length_{static_cast<ConstantSubscript>(values_.size())} {}
21464ab3302SCarolineConcatto
21564ab3302SCarolineConcatto template <int KIND>
Constant(Scalar<Result> && str)21664ab3302SCarolineConcatto Constant<Type<TypeCategory::Character, KIND>>::Constant(Scalar<Result> &&str)
21764ab3302SCarolineConcatto : values_{std::move(str)}, length_{static_cast<ConstantSubscript>(
21864ab3302SCarolineConcatto values_.size())} {}
21964ab3302SCarolineConcatto
22064ab3302SCarolineConcatto template <int KIND>
Constant(ConstantSubscript len,std::vector<Scalar<Result>> && strings,ConstantSubscripts && sh)22164ab3302SCarolineConcatto Constant<Type<TypeCategory::Character, KIND>>::Constant(ConstantSubscript len,
22264ab3302SCarolineConcatto std::vector<Scalar<Result>> &&strings, ConstantSubscripts &&sh)
22364ab3302SCarolineConcatto : ConstantBounds(std::move(sh)), length_{len} {
2247358c26dSLeandro Lupori CHECK(TotalElementCount(shape()) &&
2257358c26dSLeandro Lupori strings.size() == *TotalElementCount(shape()));
22664ab3302SCarolineConcatto values_.assign(strings.size() * length_,
22764ab3302SCarolineConcatto static_cast<typename Scalar<Result>::value_type>(' '));
22864ab3302SCarolineConcatto ConstantSubscript at{0};
22964ab3302SCarolineConcatto for (const auto &str : strings) {
23064ab3302SCarolineConcatto auto strLen{static_cast<ConstantSubscript>(str.size())};
23164ab3302SCarolineConcatto if (strLen > length_) {
23264ab3302SCarolineConcatto values_.replace(at, length_, str.substr(0, length_));
23364ab3302SCarolineConcatto } else {
23464ab3302SCarolineConcatto values_.replace(at, strLen, str);
23564ab3302SCarolineConcatto }
23664ab3302SCarolineConcatto at += length_;
23764ab3302SCarolineConcatto }
23864ab3302SCarolineConcatto CHECK(at == static_cast<ConstantSubscript>(values_.size()));
23964ab3302SCarolineConcatto }
24064ab3302SCarolineConcatto
2411f879005STim Keith template <int KIND>
~Constant()2421f879005STim Keith Constant<Type<TypeCategory::Character, KIND>>::~Constant() {}
24364ab3302SCarolineConcatto
24464ab3302SCarolineConcatto template <int KIND>
empty() const24564ab3302SCarolineConcatto bool Constant<Type<TypeCategory::Character, KIND>>::empty() const {
24664ab3302SCarolineConcatto return size() == 0;
24764ab3302SCarolineConcatto }
24864ab3302SCarolineConcatto
24964ab3302SCarolineConcatto template <int KIND>
size() const25064ab3302SCarolineConcatto std::size_t Constant<Type<TypeCategory::Character, KIND>>::size() const {
25164ab3302SCarolineConcatto if (length_ == 0) {
2527358c26dSLeandro Lupori std::optional<uint64_t> n{TotalElementCount(shape())};
2537358c26dSLeandro Lupori CHECK(n);
2547358c26dSLeandro Lupori return *n;
25564ab3302SCarolineConcatto } else {
25664ab3302SCarolineConcatto return static_cast<ConstantSubscript>(values_.size()) / length_;
25764ab3302SCarolineConcatto }
25864ab3302SCarolineConcatto }
25964ab3302SCarolineConcatto
26064ab3302SCarolineConcatto template <int KIND>
At(const ConstantSubscripts & index) const26164ab3302SCarolineConcatto auto Constant<Type<TypeCategory::Character, KIND>>::At(
26264ab3302SCarolineConcatto const ConstantSubscripts &index) const -> Scalar<Result> {
26364ab3302SCarolineConcatto auto offset{SubscriptsToOffset(index)};
26464ab3302SCarolineConcatto return values_.substr(offset * length_, length_);
26564ab3302SCarolineConcatto }
26664ab3302SCarolineConcatto
26764ab3302SCarolineConcatto template <int KIND>
Substring(ConstantSubscript lo,ConstantSubscript hi) const268bd859cb4SPeter Klausler auto Constant<Type<TypeCategory::Character, KIND>>::Substring(
269bd859cb4SPeter Klausler ConstantSubscript lo, ConstantSubscript hi) const
270bd859cb4SPeter Klausler -> std::optional<Constant> {
271bd859cb4SPeter Klausler std::vector<Element> elements;
272bd859cb4SPeter Klausler ConstantSubscript n{GetSize(shape())};
273bd859cb4SPeter Klausler ConstantSubscript newLength{0};
274bd859cb4SPeter Klausler if (lo > hi) { // zero-length results
275bd859cb4SPeter Klausler while (n-- > 0) {
276bd859cb4SPeter Klausler elements.emplace_back(); // ""
277bd859cb4SPeter Klausler }
278bd859cb4SPeter Klausler } else if (lo < 1 || hi > length_) {
279bd859cb4SPeter Klausler return std::nullopt;
280bd859cb4SPeter Klausler } else {
281bd859cb4SPeter Klausler newLength = hi - lo + 1;
282bd859cb4SPeter Klausler for (ConstantSubscripts at{lbounds()}; n-- > 0; IncrementSubscripts(at)) {
283bd859cb4SPeter Klausler elements.emplace_back(At(at).substr(lo - 1, newLength));
284bd859cb4SPeter Klausler }
285bd859cb4SPeter Klausler }
286bd859cb4SPeter Klausler return Constant{newLength, std::move(elements), ConstantSubscripts{shape()}};
287bd859cb4SPeter Klausler }
288bd859cb4SPeter Klausler
289bd859cb4SPeter Klausler template <int KIND>
Reshape(ConstantSubscripts && dims) const29064ab3302SCarolineConcatto auto Constant<Type<TypeCategory::Character, KIND>>::Reshape(
29164ab3302SCarolineConcatto ConstantSubscripts &&dims) const -> Constant<Result> {
2927358c26dSLeandro Lupori std::optional<uint64_t> optN{TotalElementCount(dims)};
2937358c26dSLeandro Lupori CHECK(optN);
2947358c26dSLeandro Lupori uint64_t n{*optN};
29564ab3302SCarolineConcatto CHECK(!empty() || n == 0);
29664ab3302SCarolineConcatto std::vector<Element> elements;
29764ab3302SCarolineConcatto ConstantSubscript at{0},
29864ab3302SCarolineConcatto limit{static_cast<ConstantSubscript>(values_.size())};
29964ab3302SCarolineConcatto while (n-- > 0) {
30064ab3302SCarolineConcatto elements.push_back(values_.substr(at, length_));
30164ab3302SCarolineConcatto at += length_;
30264ab3302SCarolineConcatto if (at == limit) { // subtle: at > limit somehow? substr() will catch it
30364ab3302SCarolineConcatto at = 0;
30464ab3302SCarolineConcatto }
30564ab3302SCarolineConcatto }
30664ab3302SCarolineConcatto return {length_, std::move(elements), std::move(dims)};
30764ab3302SCarolineConcatto }
30864ab3302SCarolineConcatto
30964ab3302SCarolineConcatto template <int KIND>
CopyFrom(const Constant<Type<TypeCategory::Character,KIND>> & source,std::size_t count,ConstantSubscripts & resultSubscripts,const std::vector<int> * dimOrder)31064ab3302SCarolineConcatto std::size_t Constant<Type<TypeCategory::Character, KIND>>::CopyFrom(
31164ab3302SCarolineConcatto const Constant<Type<TypeCategory::Character, KIND>> &source,
31264ab3302SCarolineConcatto std::size_t count, ConstantSubscripts &resultSubscripts,
31364ab3302SCarolineConcatto const std::vector<int> *dimOrder) {
31464ab3302SCarolineConcatto CHECK(length_ == source.length_);
315f72106e2SPete Steinfeld if (length_ == 0) {
316f72106e2SPete Steinfeld // It's possible that the array of strings consists of all empty strings.
317f72106e2SPete Steinfeld // If so, constant folding will result in a string that's completely empty
318f72106e2SPete Steinfeld // and the length_ will be zero, and there's nothing to do.
319f72106e2SPete Steinfeld return count;
320f72106e2SPete Steinfeld } else {
32164ab3302SCarolineConcatto std::size_t copied{0};
32264ab3302SCarolineConcatto std::size_t elementBytes{length_ * sizeof(decltype(values_[0]))};
32364ab3302SCarolineConcatto ConstantSubscripts sourceSubscripts{source.lbounds()};
32464ab3302SCarolineConcatto while (copied < count) {
32564ab3302SCarolineConcatto auto *dest{&values_.at(SubscriptsToOffset(resultSubscripts) * length_)};
32664ab3302SCarolineConcatto const auto *src{&source.values_.at(
32764ab3302SCarolineConcatto source.SubscriptsToOffset(sourceSubscripts) * length_)};
32864ab3302SCarolineConcatto std::memcpy(dest, src, elementBytes);
32964ab3302SCarolineConcatto copied++;
33064ab3302SCarolineConcatto source.IncrementSubscripts(sourceSubscripts);
33164ab3302SCarolineConcatto IncrementSubscripts(resultSubscripts, dimOrder);
33264ab3302SCarolineConcatto }
33364ab3302SCarolineConcatto return copied;
33464ab3302SCarolineConcatto }
335f72106e2SPete Steinfeld }
33664ab3302SCarolineConcatto
33764ab3302SCarolineConcatto // Constant<SomeDerived> specialization
Constant(const StructureConstructor & x)33864ab3302SCarolineConcatto Constant<SomeDerived>::Constant(const StructureConstructor &x)
33964ab3302SCarolineConcatto : Base{x.values(), Result{x.derivedTypeSpec()}} {}
34064ab3302SCarolineConcatto
Constant(StructureConstructor && x)34164ab3302SCarolineConcatto Constant<SomeDerived>::Constant(StructureConstructor &&x)
34264ab3302SCarolineConcatto : Base{std::move(x.values()), Result{x.derivedTypeSpec()}} {}
34364ab3302SCarolineConcatto
Constant(const semantics::DerivedTypeSpec & spec,std::vector<StructureConstructorValues> && x,ConstantSubscripts && s)34464ab3302SCarolineConcatto Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
34564ab3302SCarolineConcatto std::vector<StructureConstructorValues> &&x, ConstantSubscripts &&s)
34664ab3302SCarolineConcatto : Base{std::move(x), std::move(s), Result{spec}} {}
34764ab3302SCarolineConcatto
AcquireValues(std::vector<StructureConstructor> && x)34864ab3302SCarolineConcatto static std::vector<StructureConstructorValues> AcquireValues(
34964ab3302SCarolineConcatto std::vector<StructureConstructor> &&x) {
35064ab3302SCarolineConcatto std::vector<StructureConstructorValues> result;
35164ab3302SCarolineConcatto for (auto &&structure : std::move(x)) {
35264ab3302SCarolineConcatto result.emplace_back(std::move(structure.values()));
35364ab3302SCarolineConcatto }
35464ab3302SCarolineConcatto return result;
35564ab3302SCarolineConcatto }
35664ab3302SCarolineConcatto
Constant(const semantics::DerivedTypeSpec & spec,std::vector<StructureConstructor> && x,ConstantSubscripts && shape)35764ab3302SCarolineConcatto Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
35864ab3302SCarolineConcatto std::vector<StructureConstructor> &&x, ConstantSubscripts &&shape)
35964ab3302SCarolineConcatto : Base{AcquireValues(std::move(x)), std::move(shape), Result{spec}} {}
36064ab3302SCarolineConcatto
36164ab3302SCarolineConcatto std::optional<StructureConstructor>
GetScalarValue() const36264ab3302SCarolineConcatto Constant<SomeDerived>::GetScalarValue() const {
36364ab3302SCarolineConcatto if (Rank() == 0) {
36464ab3302SCarolineConcatto return StructureConstructor{result().derivedTypeSpec(), values_.at(0)};
36564ab3302SCarolineConcatto } else {
36664ab3302SCarolineConcatto return std::nullopt;
36764ab3302SCarolineConcatto }
36864ab3302SCarolineConcatto }
36964ab3302SCarolineConcatto
At(const ConstantSubscripts & index) const37064ab3302SCarolineConcatto StructureConstructor Constant<SomeDerived>::At(
37164ab3302SCarolineConcatto const ConstantSubscripts &index) const {
37264ab3302SCarolineConcatto return {result().derivedTypeSpec(), values_.at(SubscriptsToOffset(index))};
37364ab3302SCarolineConcatto }
37464ab3302SCarolineConcatto
operator ==(const Constant<SomeDerived> & that) const375e47fbb7cSSlava Zakharin bool Constant<SomeDerived>::operator==(
376e47fbb7cSSlava Zakharin const Constant<SomeDerived> &that) const {
377e47fbb7cSSlava Zakharin return result().derivedTypeSpec() == that.result().derivedTypeSpec() &&
378e47fbb7cSSlava Zakharin shape() == that.shape() && values_ == that.values_;
379e47fbb7cSSlava Zakharin }
380e47fbb7cSSlava Zakharin
Reshape(ConstantSubscripts && dims) const38164ab3302SCarolineConcatto auto Constant<SomeDerived>::Reshape(ConstantSubscripts &&dims) const
38264ab3302SCarolineConcatto -> Constant {
38364ab3302SCarolineConcatto return {result().derivedTypeSpec(), Base::Reshape(dims), std::move(dims)};
38464ab3302SCarolineConcatto }
38564ab3302SCarolineConcatto
CopyFrom(const Constant<SomeDerived> & source,std::size_t count,ConstantSubscripts & resultSubscripts,const std::vector<int> * dimOrder)38664ab3302SCarolineConcatto std::size_t Constant<SomeDerived>::CopyFrom(const Constant<SomeDerived> &source,
38764ab3302SCarolineConcatto std::size_t count, ConstantSubscripts &resultSubscripts,
38864ab3302SCarolineConcatto const std::vector<int> *dimOrder) {
38964ab3302SCarolineConcatto return Base::CopyFrom(source, count, resultSubscripts, dimOrder);
39064ab3302SCarolineConcatto }
39164ab3302SCarolineConcatto
operator ()(SymbolRef x,SymbolRef y) const3920d8331c0Speter klausler bool ComponentCompare::operator()(SymbolRef x, SymbolRef y) const {
3930d8331c0Speter klausler return semantics::SymbolSourcePositionCompare{}(x, y);
3940d8331c0Speter klausler }
3950d8331c0Speter klausler
3965c5bde1bSPeter Klausler #ifdef _MSC_VER // disable bogus warning about missing definitions
3975c5bde1bSPeter Klausler #pragma warning(disable : 4661)
3985c5bde1bSPeter Klausler #endif
39964ab3302SCarolineConcatto INSTANTIATE_CONSTANT_TEMPLATES
4001f879005STim Keith } // namespace Fortran::evaluate
401