2019-01-28 23:38:17 +01:00
|
|
|
// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#include "constant.h"
|
2019-02-07 21:05:27 +01:00
|
|
|
#include "expression.h"
|
2019-05-22 01:58:46 +02:00
|
|
|
#include "shape.h"
|
2019-01-28 23:38:17 +01:00
|
|
|
#include "type.h"
|
2019-03-01 01:30:55 +01:00
|
|
|
#include <string>
|
2019-01-28 23:38:17 +01:00
|
|
|
|
|
|
|
namespace Fortran::evaluate {
|
2019-02-07 21:05:27 +01:00
|
|
|
|
2019-04-18 23:11:15 +02:00
|
|
|
std::size_t TotalElementCount(const ConstantSubscripts &shape) {
|
|
|
|
std::size_t size{1};
|
|
|
|
for (auto dim : shape) {
|
|
|
|
CHECK(dim >= 0);
|
|
|
|
size *= dim;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IncrementSubscripts(
|
|
|
|
ConstantSubscripts &indices, const ConstantSubscripts &shape) {
|
2019-05-22 01:58:46 +02:00
|
|
|
int rank{GetRank(shape)};
|
|
|
|
CHECK(GetRank(indices) == rank);
|
|
|
|
for (int j{0}; j < rank; ++j) {
|
2019-04-18 23:11:15 +02:00
|
|
|
CHECK(indices[j] >= 1);
|
|
|
|
if (++indices[j] <= shape[j]) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
CHECK(indices[j] == shape[j] + 1);
|
|
|
|
indices[j] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false; // all done
|
|
|
|
}
|
|
|
|
|
2019-05-22 01:58:46 +02:00
|
|
|
template<typename RESULT, typename ELEMENT>
|
|
|
|
ConstantBase<RESULT, ELEMENT>::ConstantBase(
|
|
|
|
std::vector<Element> &&x, ConstantSubscripts &&dims, Result res)
|
|
|
|
: result_{res}, values_(std::move(x)), shape_(std::move(dims)) {
|
|
|
|
CHECK(size() == TotalElementCount(shape_));
|
|
|
|
}
|
|
|
|
|
2019-05-13 18:33:18 +02:00
|
|
|
template<typename RESULT, typename ELEMENT>
|
|
|
|
ConstantBase<RESULT, ELEMENT>::~ConstantBase() {}
|
|
|
|
|
|
|
|
template<typename RESULT, typename ELEMENT>
|
|
|
|
bool ConstantBase<RESULT, ELEMENT>::operator==(const ConstantBase &that) const {
|
|
|
|
return shape_ == that.shape_ && values_ == that.values_;
|
|
|
|
}
|
2019-02-07 21:05:27 +01:00
|
|
|
|
2019-04-18 23:11:15 +02:00
|
|
|
static ConstantSubscript SubscriptsToOffset(
|
|
|
|
const ConstantSubscripts &index, const ConstantSubscripts &shape) {
|
2019-05-22 01:58:46 +02:00
|
|
|
CHECK(GetRank(index) == GetRank(shape));
|
2019-04-18 23:11:15 +02:00
|
|
|
ConstantSubscript stride{1}, offset{0};
|
2019-02-01 22:37:49 +01:00
|
|
|
int dim{0};
|
2019-04-18 23:11:15 +02:00
|
|
|
for (auto j : index) {
|
|
|
|
auto bound{shape[dim++]};
|
2019-02-01 22:37:49 +01:00
|
|
|
CHECK(j >= 1 && j <= bound);
|
|
|
|
offset += stride * (j - 1);
|
|
|
|
stride *= bound;
|
|
|
|
}
|
2019-02-11 23:56:03 +01:00
|
|
|
return offset;
|
2019-02-01 22:37:49 +01:00
|
|
|
}
|
|
|
|
|
2019-05-22 01:58:46 +02:00
|
|
|
template<typename RESULT, typename ELEMENT>
|
|
|
|
Constant<SubscriptInteger> ConstantBase<RESULT, ELEMENT>::SHAPE() const {
|
|
|
|
return AsConstantShape(shape_);
|
2019-02-11 23:56:03 +01:00
|
|
|
}
|
|
|
|
|
2019-05-13 18:33:18 +02:00
|
|
|
template<typename RESULT, typename ELEMENT>
|
2019-05-22 01:58:46 +02:00
|
|
|
auto ConstantBase<RESULT, ELEMENT>::Reshape(
|
|
|
|
const ConstantSubscripts &dims) const -> std::vector<Element> {
|
|
|
|
std::size_t n{TotalElementCount(dims)};
|
|
|
|
CHECK(!empty() || n == 0);
|
|
|
|
std::vector<Element> elements;
|
|
|
|
auto iter{values().cbegin()};
|
|
|
|
while (n-- > 0) {
|
|
|
|
elements.push_back(*iter);
|
|
|
|
if (++iter == values().cend()) {
|
|
|
|
iter = values().cbegin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return elements;
|
2019-02-11 23:56:03 +01:00
|
|
|
}
|
|
|
|
|
2019-05-13 18:33:18 +02:00
|
|
|
template<typename T>
|
|
|
|
auto Constant<T>::At(const ConstantSubscripts &index) const -> Element {
|
|
|
|
return Base::values_.at(SubscriptsToOffset(index, Base::shape_));
|
|
|
|
}
|
|
|
|
|
2019-05-22 01:58:46 +02:00
|
|
|
template<typename T>
|
|
|
|
auto Constant<T>::Reshape(ConstantSubscripts &&dims) const -> Constant {
|
|
|
|
return {Base::Reshape(dims), std::move(dims)};
|
|
|
|
}
|
|
|
|
|
2019-02-15 21:20:30 +01:00
|
|
|
// Constant<Type<TypeCategory::Character, KIND> specializations
|
2019-02-11 23:56:03 +01:00
|
|
|
template<int KIND>
|
2019-05-13 18:33:18 +02:00
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::Constant(
|
|
|
|
const Scalar<Result> &str)
|
2019-06-07 18:57:10 +02:00
|
|
|
: values_{str}, length_{static_cast<ConstantSubscript>(values_.size())} {}
|
2019-02-11 23:56:03 +01:00
|
|
|
|
|
|
|
template<int KIND>
|
2019-05-13 18:33:18 +02:00
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::Constant(Scalar<Result> &&str)
|
2019-06-07 18:57:10 +02:00
|
|
|
: values_{std::move(str)}, length_{static_cast<ConstantSubscript>(
|
|
|
|
values_.size())} {}
|
2019-02-11 23:56:03 +01:00
|
|
|
|
|
|
|
template<int KIND>
|
2019-06-07 18:57:10 +02:00
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::Constant(ConstantSubscript len,
|
2019-05-13 18:33:18 +02:00
|
|
|
std::vector<Scalar<Result>> &&strings, ConstantSubscripts &&dims)
|
2019-03-01 01:30:55 +01:00
|
|
|
: length_{len}, shape_{std::move(dims)} {
|
2019-05-22 01:58:46 +02:00
|
|
|
CHECK(strings.size() == TotalElementCount(shape_));
|
2019-02-11 23:56:03 +01:00
|
|
|
values_.assign(strings.size() * length_,
|
2019-05-13 18:33:18 +02:00
|
|
|
static_cast<typename Scalar<Result>::value_type>(' '));
|
2019-06-07 18:57:10 +02:00
|
|
|
ConstantSubscript at{0};
|
2019-02-11 23:56:03 +01:00
|
|
|
for (const auto &str : strings) {
|
2019-06-07 18:57:10 +02:00
|
|
|
auto strLen{static_cast<ConstantSubscript>(str.size())};
|
2019-02-15 21:20:30 +01:00
|
|
|
if (strLen > length_) {
|
|
|
|
values_.replace(at, length_, str.substr(0, length_));
|
|
|
|
} else {
|
|
|
|
values_.replace(at, strLen, str);
|
|
|
|
}
|
2019-02-11 23:56:03 +01:00
|
|
|
at += length_;
|
|
|
|
}
|
2019-06-07 18:57:10 +02:00
|
|
|
CHECK(at == static_cast<ConstantSubscript>(values_.size()));
|
2019-01-28 23:38:17 +01:00
|
|
|
}
|
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
template<int KIND> Constant<Type<TypeCategory::Character, KIND>>::~Constant() {}
|
|
|
|
|
2019-02-12 01:02:14 +01:00
|
|
|
template<int KIND>
|
|
|
|
bool Constant<Type<TypeCategory::Character, KIND>>::empty() const {
|
|
|
|
return size() == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
std::size_t Constant<Type<TypeCategory::Character, KIND>>::size() const {
|
|
|
|
if (length_ == 0) {
|
2019-05-22 01:58:46 +02:00
|
|
|
return TotalElementCount(shape_);
|
2019-02-12 01:02:14 +01:00
|
|
|
} else {
|
2019-06-07 18:57:10 +02:00
|
|
|
return static_cast<ConstantSubscript>(values_.size()) / length_;
|
2019-02-12 01:02:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
template<int KIND>
|
|
|
|
auto Constant<Type<TypeCategory::Character, KIND>>::At(
|
2019-05-13 18:33:18 +02:00
|
|
|
const ConstantSubscripts &index) const -> Scalar<Result> {
|
2019-02-11 23:56:03 +01:00
|
|
|
auto offset{SubscriptsToOffset(index, shape_)};
|
2019-05-13 18:33:18 +02:00
|
|
|
return values_.substr(offset * length_, length_);
|
2019-02-11 23:56:03 +01:00
|
|
|
}
|
|
|
|
|
2019-05-22 01:58:46 +02:00
|
|
|
template<int KIND>
|
|
|
|
auto Constant<Type<TypeCategory::Character, KIND>>::Reshape(
|
|
|
|
ConstantSubscripts &&dims) const -> Constant<Result> {
|
|
|
|
std::size_t n{TotalElementCount(dims)};
|
|
|
|
CHECK(!empty() || n == 0);
|
|
|
|
std::vector<Element> elements;
|
2019-06-07 18:57:10 +02:00
|
|
|
ConstantSubscript at{0},
|
|
|
|
limit{static_cast<ConstantSubscript>(values_.size())};
|
2019-05-22 01:58:46 +02:00
|
|
|
while (n-- > 0) {
|
|
|
|
elements.push_back(values_.substr(at, length_));
|
|
|
|
at += length_;
|
|
|
|
if (at == limit) { // subtle: at > limit somehow? substr() will catch it
|
|
|
|
at = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {length_, std::move(elements), std::move(dims)};
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
template<int KIND>
|
|
|
|
Constant<SubscriptInteger>
|
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::SHAPE() const {
|
2019-05-22 01:58:46 +02:00
|
|
|
return AsConstantShape(shape_);
|
2019-02-11 23:56:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Constant<SomeDerived> specialization
|
2019-02-08 19:39:10 +01:00
|
|
|
Constant<SomeDerived>::Constant(const StructureConstructor &x)
|
2019-05-13 18:33:18 +02:00
|
|
|
: Base{x.values(), Result{x.derivedTypeSpec()}} {}
|
2019-02-08 19:39:10 +01:00
|
|
|
|
|
|
|
Constant<SomeDerived>::Constant(StructureConstructor &&x)
|
2019-05-13 18:33:18 +02:00
|
|
|
: Base{std::move(x.values()), Result{x.derivedTypeSpec()}} {}
|
2019-02-08 19:39:10 +01:00
|
|
|
|
|
|
|
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
|
2019-04-18 23:11:15 +02:00
|
|
|
std::vector<StructureConstructorValues> &&x, ConstantSubscripts &&s)
|
2019-05-13 18:33:18 +02:00
|
|
|
: Base{std::move(x), std::move(s), Result{spec}} {}
|
2019-02-08 19:39:10 +01:00
|
|
|
|
2019-04-18 23:11:15 +02:00
|
|
|
static std::vector<StructureConstructorValues> AcquireValues(
|
2019-02-08 19:39:10 +01:00
|
|
|
std::vector<StructureConstructor> &&x) {
|
|
|
|
std::vector<StructureConstructorValues> result;
|
|
|
|
for (auto &&structure : std::move(x)) {
|
|
|
|
result.emplace_back(std::move(structure.values()));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-02-07 21:05:27 +01:00
|
|
|
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
|
2019-04-18 23:11:15 +02:00
|
|
|
std::vector<StructureConstructor> &&x, ConstantSubscripts &&s)
|
2019-05-13 18:33:18 +02:00
|
|
|
: Base{AcquireValues(std::move(x)), std::move(s), Result{spec}} {}
|
|
|
|
|
|
|
|
std::optional<StructureConstructor>
|
|
|
|
Constant<SomeDerived>::GetScalarValue() const {
|
|
|
|
if (shape_.empty()) {
|
|
|
|
return StructureConstructor{result().derivedTypeSpec(), values_.at(0)};
|
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StructureConstructor Constant<SomeDerived>::At(
|
|
|
|
const ConstantSubscripts &index) const {
|
|
|
|
return {result().derivedTypeSpec(),
|
|
|
|
values_.at(SubscriptsToOffset(index, shape_))};
|
|
|
|
}
|
2019-02-07 21:05:27 +01:00
|
|
|
|
2019-05-22 01:58:46 +02:00
|
|
|
auto Constant<SomeDerived>::Reshape(ConstantSubscripts &&dims) const
|
|
|
|
-> Constant {
|
|
|
|
return {result().derivedTypeSpec(), Base::Reshape(dims), std::move(dims)};
|
|
|
|
}
|
|
|
|
|
2019-03-27 23:27:33 +01:00
|
|
|
INSTANTIATE_CONSTANT_TEMPLATES
|
2019-01-28 23:38:17 +01:00
|
|
|
}
|