Skip to content

Commit

Permalink
Merge branch 'main' into chiphogg/chrono-interop
Browse files Browse the repository at this point in the history
  • Loading branch information
chiphogg committed Nov 28, 2023
2 parents 67f6482 + 8fa4e38 commit 2726bb4
Show file tree
Hide file tree
Showing 6 changed files with 693 additions and 11 deletions.
32 changes: 27 additions & 5 deletions au/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,23 @@ cc_test(
)

cc_library(
name = "operators",
hdrs = ["operators.hh"],
name = "constant",
hdrs = ["constant.hh"],
deps = [
":quantity",
":unit_of_measure",
":wrapper_operations",
],
)

cc_test(
name = "operators_test",
name = "constant_test",
size = "small",
srcs = ["operators_test.cc"],
srcs = ["constant_test.cc"],
deps = [
":operators",
":constant",
":testing",
":units",
"@com_google_googletest//:gtest_main",
],
)
Expand Down Expand Up @@ -286,6 +292,22 @@ cc_test(
],
)

cc_library(
name = "operators",
hdrs = ["operators.hh"],
)

cc_test(
name = "operators_test",
size = "small",
srcs = ["operators_test.cc"],
deps = [
":operators",
":testing",
"@com_google_googletest//:gtest_main",
],
)

cc_library(
name = "packs",
hdrs = ["packs.hh"],
Expand Down
105 changes: 105 additions & 0 deletions au/constant.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2023 Aurora Operations, Inc.
//
// 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.

#pragma once

#include "au/quantity.hh"
#include "au/quantity_point.hh"
#include "au/stdx/type_traits.hh"
#include "au/unit_of_measure.hh"
#include "au/wrapper_operations.hh"

namespace au {

//
// A monovalue type to represent a constant value, including its units, if any.
//
// Users can multiply or divide `Constant` instances by raw numbers or `Quantity` instances, and it
// will perform symbolic arithmetic at compile time without affecting the stored numeric value.
// `Constant` also composes with other constants, and with `QuantityMaker` and other related types.
//
// Although `Constant` does not have any specific numeric type associated with it (as opposed to
// `Quantity`), it can easily convert to any appropriate `Quantity` type, with any rep. Unlike
// `Quantity`, these conversions support _exact_ safety checks, so that every conversion producing a
// correctly representable value will succeed, and every unrepresentable conversion will fail.
//
template <typename Unit>
struct Constant : detail::MakesQuantityFromNumber<Constant, Unit>,
detail::ScalesQuantity<Constant, Unit>,
detail::ComposesWith<Constant, Unit, Constant, Constant>,
detail::ComposesWith<Constant, Unit, QuantityMaker, QuantityMaker>,
detail::ComposesWith<Constant, Unit, SingularNameFor, SingularNameFor>,
detail::ForbidsComposingWith<Constant, Unit, QuantityPointMaker>,
detail::ForbidsComposingWith<Constant, Unit, QuantityPoint>,
detail::CanScaleByMagnitude<Constant, Unit> {
// Convert this constant to a Quantity of the given rep.
template <typename T>
constexpr auto as() const {
return make_quantity<Unit>(static_cast<T>(1));
}

// Convert this constant to a Quantity of the given unit and rep, ignoring safety checks.
template <typename T, typename OtherUnit>
constexpr auto coerce_as(OtherUnit u) const {
return as<T>().coerce_as(u);
}

// Convert this constant to a Quantity of the given unit and rep.
template <typename T, typename OtherUnit>
constexpr auto as(OtherUnit u) const {
static_assert(can_store_value_in<T>(u), "Cannot represent constant in this unit/rep");
return coerce_as<T>(u);
}

// Get the value of this constant in the given unit and rep, ignoring safety checks.
template <typename T, typename OtherUnit>
constexpr auto coerce_in(OtherUnit u) const {
return as<T>().coerce_in(u);
}

// Get the value of this constant in the given unit and rep.
template <typename T, typename OtherUnit>
constexpr auto in(OtherUnit u) const {
static_assert(can_store_value_in<T>(u), "Cannot represent constant in this unit/rep");
return coerce_in<T>(u);
}

// Implicitly convert to any quantity type which passes safety checks.
template <typename U, typename R>
constexpr operator Quantity<U, R>() const {
return as<R>(U{});
}

// Static function to check whether this constant can be exactly-represented in the given rep
// `T` and unit `OtherUnit`.
template <typename T, typename OtherUnit>
static constexpr bool can_store_value_in(OtherUnit other) {
return representable_in<T>(unit_ratio(Unit{}, other));
}
};

// Make a constant from the given unit.
//
// Note that the argument is a _unit slot_, and thus can also accept things like `QuantityMaker` and
// `SymbolFor` in addition to regular units.
template <typename UnitSlot>
constexpr Constant<AssociatedUnitT<UnitSlot>> make_constant(UnitSlot) {
return {};
}

// Support using `Constant` in a unit slot.
template <typename Unit>
struct AssociatedUnit<Constant<Unit>> : stdx::type_identity<Unit> {};

} // namespace au
Loading

0 comments on commit 2726bb4

Please sign in to comment.