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-01-28 23:38:17 +01:00
|
|
|
#include "type.h"
|
|
|
|
#include "../parser/characters.h"
|
2019-02-11 23:56:03 +01:00
|
|
|
#include <algorithm>
|
2019-01-28 23:38:17 +01:00
|
|
|
|
|
|
|
namespace Fortran::evaluate {
|
2019-02-07 21:05:27 +01:00
|
|
|
|
2019-02-08 19:39:10 +01:00
|
|
|
template<typename RESULT, typename VALUE>
|
|
|
|
ConstantBase<RESULT, VALUE>::~ConstantBase() {}
|
2019-02-07 21:05:27 +01:00
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
static void ShapeAsFortran(
|
|
|
|
std::ostream &o, const std::vector<std::int64_t> &shape) {
|
|
|
|
if (shape.size() > 1) {
|
|
|
|
o << ",shape=";
|
|
|
|
char ch{'['};
|
|
|
|
for (auto dim : shape) {
|
|
|
|
o << ch << dim;
|
|
|
|
ch = ',';
|
|
|
|
}
|
|
|
|
o << "])";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 19:39:10 +01:00
|
|
|
template<typename RESULT, typename VALUE>
|
|
|
|
std::ostream &ConstantBase<RESULT, VALUE>::AsFortran(std::ostream &o) const {
|
2019-01-29 19:22:18 +01:00
|
|
|
if (Rank() > 1) {
|
|
|
|
o << "reshape(";
|
|
|
|
}
|
2019-01-28 23:38:17 +01:00
|
|
|
if (Rank() > 0) {
|
2019-01-29 19:22:18 +01:00
|
|
|
o << '[' << GetType().AsFortran() << "::";
|
2019-01-28 23:38:17 +01:00
|
|
|
}
|
2019-01-29 19:22:18 +01:00
|
|
|
bool first{true};
|
2019-01-28 23:38:17 +01:00
|
|
|
for (const auto &value : values_) {
|
2019-01-29 19:22:18 +01:00
|
|
|
if (first) {
|
|
|
|
first = false;
|
|
|
|
} else {
|
|
|
|
o << ',';
|
|
|
|
}
|
2019-02-08 19:39:10 +01:00
|
|
|
if constexpr (Result::category == TypeCategory::Integer) {
|
|
|
|
o << value.SignedDecimal() << '_' << Result::kind;
|
|
|
|
} else if constexpr (Result::category == TypeCategory::Real ||
|
|
|
|
Result::category == TypeCategory::Complex) {
|
|
|
|
value.AsFortran(o, Result::kind);
|
|
|
|
} else if constexpr (Result::category == TypeCategory::Character) {
|
|
|
|
o << Result::kind << '_' << parser::QuoteCharacterLiteral(value);
|
|
|
|
} else if constexpr (Result::category == TypeCategory::Logical) {
|
2019-01-28 23:38:17 +01:00
|
|
|
if (value.IsTrue()) {
|
|
|
|
o << ".true.";
|
|
|
|
} else {
|
|
|
|
o << ".false.";
|
|
|
|
}
|
|
|
|
o << '_' << Result::kind;
|
|
|
|
} else {
|
2019-02-08 19:39:10 +01:00
|
|
|
StructureConstructor{AsConstant().derivedTypeSpec(), value}.AsFortran(o);
|
2019-01-28 23:38:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Rank() > 0) {
|
2019-01-29 19:22:18 +01:00
|
|
|
o << ']';
|
|
|
|
}
|
2019-02-11 23:56:03 +01:00
|
|
|
ShapeAsFortran(o, shape_);
|
2019-01-28 23:38:17 +01:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
static std::int64_t SubscriptsToOffset(const std::vector<std::int64_t> &index,
|
|
|
|
const std::vector<std::int64_t> &shape) {
|
|
|
|
CHECK(index.size() == shape.size());
|
2019-02-01 22:37:49 +01:00
|
|
|
std::int64_t stride{1}, offset{0};
|
|
|
|
int dim{0};
|
|
|
|
for (std::int64_t j : index) {
|
2019-02-11 23:56:03 +01:00
|
|
|
std::int64_t 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-02-08 19:39:10 +01:00
|
|
|
template<typename RESULT, typename VALUE>
|
2019-02-11 23:56:03 +01:00
|
|
|
auto ConstantBase<RESULT, VALUE>::At(
|
|
|
|
const std::vector<std::int64_t> &index) const -> ScalarValue {
|
|
|
|
return values_.at(SubscriptsToOffset(index, shape_));
|
|
|
|
}
|
|
|
|
|
|
|
|
static Constant<SubscriptInteger> ShapeAsConstant(
|
|
|
|
const std::vector<std::int64_t> &shape) {
|
2019-01-28 23:38:17 +01:00
|
|
|
using IntType = Scalar<SubscriptInteger>;
|
|
|
|
std::vector<IntType> result;
|
2019-02-11 23:56:03 +01:00
|
|
|
for (std::int64_t dim : shape) {
|
2019-01-28 23:38:17 +01:00
|
|
|
result.emplace_back(dim);
|
|
|
|
}
|
2019-02-11 23:56:03 +01:00
|
|
|
return {std::move(result),
|
|
|
|
std::vector<std::int64_t>{static_cast<std::int64_t>(shape.size())}};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename RESULT, typename VALUE>
|
|
|
|
Constant<SubscriptInteger> ConstantBase<RESULT, VALUE>::SHAPE() const {
|
|
|
|
return ShapeAsConstant(shape_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Constant<Type<TypeCategory::Character, KIND> specializations
|
|
|
|
template<int KIND>
|
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::Constant(const ScalarValue &str)
|
|
|
|
: values_{str}, length_{static_cast<std::int64_t>(values_.size())} {}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::Constant(ScalarValue &&str)
|
|
|
|
: values_{std::move(str)}, length_{
|
|
|
|
static_cast<std::int64_t>(values_.size())} {}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::Constant(std::int64_t len,
|
|
|
|
std::vector<ScalarValue> &&strings, std::vector<std::int64_t> &&dims)
|
|
|
|
: length_{len} {
|
|
|
|
values_.assign(strings.size() * length_,
|
|
|
|
static_cast<typename ScalarValue::value_type>(' '));
|
|
|
|
std::int64_t at{0};
|
|
|
|
for (const auto &str : strings) {
|
|
|
|
values_.replace(
|
|
|
|
at, std::min(length_, static_cast<std::int64_t>(str.size())), str);
|
|
|
|
at += length_;
|
|
|
|
}
|
|
|
|
CHECK(at == static_cast<std::int64_t>(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
|
|
|
static std::int64_t ShapeElements(const std::vector<std::int64_t> &shape) {
|
|
|
|
std::int64_t elements{1};
|
|
|
|
for (auto dim : shape) {
|
|
|
|
elements *= dim;
|
|
|
|
}
|
|
|
|
return elements;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
return ShapeElements(shape_);
|
|
|
|
} else {
|
|
|
|
return static_cast<std::int64_t>(values_.size()) / length_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
template<int KIND>
|
|
|
|
auto Constant<Type<TypeCategory::Character, KIND>>::At(
|
|
|
|
const std::vector<std::int64_t> &index) const -> ScalarValue {
|
|
|
|
auto offset{SubscriptsToOffset(index, shape_)};
|
|
|
|
return values_.substr(offset, length_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
Constant<SubscriptInteger>
|
|
|
|
Constant<Type<TypeCategory::Character, KIND>>::SHAPE() const {
|
|
|
|
return ShapeAsConstant(shape_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<int KIND>
|
|
|
|
std::ostream &Constant<Type<TypeCategory::Character, KIND>>::AsFortran(
|
|
|
|
std::ostream &o) const {
|
|
|
|
if (Rank() > 1) {
|
|
|
|
o << "reshape(";
|
|
|
|
}
|
|
|
|
if (Rank() > 0) {
|
|
|
|
o << '[' << GetType().AsFortran() << "::";
|
|
|
|
}
|
|
|
|
auto total{static_cast<std::int64_t>(size())};
|
2019-02-12 01:02:14 +01:00
|
|
|
for (std::int64_t j{0}; j < total; ++j) {
|
|
|
|
ScalarValue value{values_.substr(j * length_, length_)};
|
|
|
|
if (j > 0) {
|
2019-02-11 23:56:03 +01:00
|
|
|
o << ',';
|
|
|
|
}
|
|
|
|
o << Result::kind << '_' << parser::QuoteCharacterLiteral(value);
|
|
|
|
}
|
|
|
|
if (Rank() > 0) {
|
|
|
|
o << ']';
|
|
|
|
}
|
|
|
|
ShapeAsFortran(o, shape_);
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Constant<SomeDerived> specialization
|
2019-02-08 19:39:10 +01:00
|
|
|
Constant<SomeDerived>::Constant(const StructureConstructor &x)
|
|
|
|
: Base{x.values()}, derivedTypeSpec_{&x.derivedTypeSpec()} {}
|
|
|
|
|
|
|
|
Constant<SomeDerived>::Constant(StructureConstructor &&x)
|
|
|
|
: Base{std::move(x.values())}, derivedTypeSpec_{&x.derivedTypeSpec()} {}
|
|
|
|
|
|
|
|
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
|
|
|
|
std::vector<StructureConstructorValues> &&x, std::vector<std::int64_t> &&s)
|
|
|
|
: Base{std::move(x), std::move(s)}, derivedTypeSpec_{&spec} {}
|
|
|
|
|
|
|
|
static std::vector<StructureConstructorValues> GetValues(
|
|
|
|
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,
|
|
|
|
std::vector<StructureConstructor> &&x, std::vector<std::int64_t> &&s)
|
2019-02-08 19:39:10 +01:00
|
|
|
: Base{GetValues(std::move(x)), std::move(s)}, derivedTypeSpec_{&spec} {}
|
2019-02-07 21:05:27 +01:00
|
|
|
|
2019-02-11 23:56:03 +01:00
|
|
|
FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase)
|
2019-02-08 19:39:10 +01:00
|
|
|
template class ConstantBase<SomeDerived, StructureConstructorValues>;
|
2019-01-28 23:38:17 +01:00
|
|
|
FOR_EACH_INTRINSIC_KIND(template class Constant)
|
|
|
|
}
|