Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added unary isometric helpers for comparison to, substitution of IEEE specials. #102

Merged
merged 2 commits into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions include/tatami/isometric/compare_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,37 @@ void delayed_compare_run(Value_& val, Value_ scalar) {
* @endcond
*/

/**
* Type of comparison operation for special IEEE values.
*/
enum class SpecialCompareOperation : char {
ISNAN,
ISINF,
ISFINITE
};

/**
* @cond
*/
template<SpecialCompareOperation op_, bool pass_, typename Value_>
bool delayed_special_compare(Value_ val) {
if constexpr(op_ == SpecialCompareOperation::ISNAN) {
return pass_ == std::isnan(val);
} else if constexpr(op_ == SpecialCompareOperation::ISINF) {
return pass_ == std::isinf(val);
} else {
return pass_ == std::isfinite(val);
}
}

template<SpecialCompareOperation op_, bool pass_, typename Value_>
void delayed_special_compare_run(Value_& val) {
val = delayed_special_compare<op_, pass_, Value_>(val);
}
/**
* @endcond
*/

}

#endif
111 changes: 111 additions & 0 deletions include/tatami/isometric/unary/compare_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,117 @@ DelayedUnaryIsometricCompareVector<CompareOperation::NOT_EQUAL, Value_, Vector_>
return DelayedUnaryIsometricCompareVector<CompareOperation::NOT_EQUAL, Value_, Vector_>(std::move(vector), by_row);
}

/**
* @cond
*/
template<SpecialCompareOperation op_, bool pass_, typename Value_, typename Index_>
void delayed_special_compare_run_simple(Value_* buffer, Index_ length) {
for (Index_ i = 0; i < length; ++i) {
delayed_special_compare_run<op_, pass_, Value_>(buffer[i]);
}
}

template<SpecialCompareOperation op_, bool pass_, typename Value_>
bool delayed_special_compare_actual_sparse() {
return !delayed_special_compare<op_, pass_, Value_>(0);
}
/**
* @endcond
*/

/**
* @brief Delayed special value comparison.
*
* This should be used as the `Operation_` in the `DelayedUnaryIsometricOperation` class.
*
* @tparam op_ The special comparison operation.
* @tparam pass_ Whether to return true if the special comparison is true.
* @tparam Value_ Floating-point type of the data value.
*/
template<SpecialCompareOperation op_, bool pass_, typename Value_ = double>
class DelayedUnaryIsometricSpecialCompare {
public:
DelayedUnaryIsometricSpecialCompare() {
my_sparse = !delayed_special_compare<op_, pass_, Value_>(0);
}

private:
bool my_sparse;

public:
/**
* @cond
*/
static constexpr bool is_basic = false;

bool is_sparse() const {
return my_sparse;
}
/**
* @endcond
*/

public:
/**
* @cond
*/
template<typename Index_>
void dense(bool, Index_, Index_, Index_ length, Value_* buffer) const {
delayed_special_compare_run_simple<op_, pass_>(buffer, length);
}

template<typename Index_>
void dense(bool, Index_, const std::vector<Index_>& indices, Value_* buffer) const {
delayed_special_compare_run_simple<op_, pass_>(buffer, static_cast<Index_>(indices.size()));
}

template<typename Index_>
void sparse(bool, Index_, Index_ number, Value_* buffer, const Index_*) const {
delayed_special_compare_run_simple<op_, pass_>(buffer, number);
}

template<typename Index_>
Value_ fill(bool, Index_) const {
return static_cast<Value_>(!my_sparse);
}
/**
* @endcond
*/
};

/**
* @tparam pass_ Whether to return truthy if the matrix value is NaN.
* @tparam Value_ Type of the data value.
* @return A helper class for a delayed NaN check,
* to be used as the `operation` in a `DelayedUnaryIsometricOperation`.
*/
template<bool pass_ = true, typename Value_ = double>
DelayedUnaryIsometricSpecialCompare<SpecialCompareOperation::ISNAN, pass_, Value_> make_DelayedUnaryIsometricIsnan() {
return DelayedUnaryIsometricSpecialCompare<SpecialCompareOperation::ISNAN, pass_, Value_>();
}

/**
* @tparam pass_ Whether to return truthy if the matrix value is infinite.
* @tparam Value_ Type of the data value.
* @return A helper class for a delayed check for infinity (positive or negative),
* to be used as the `operation` in a `DelayedUnaryIsometricOperation`.
*/
template<bool pass_ = true, typename Value_ = double>
DelayedUnaryIsometricSpecialCompare<SpecialCompareOperation::ISINF, pass_, Value_> make_DelayedUnaryIsometricIsinf() {
return DelayedUnaryIsometricSpecialCompare<SpecialCompareOperation::ISINF, pass_, Value_>();
}

/**
* @tparam pass_ Whether to return truthy if the matrix value is finite.
* @tparam Value_ Type of the data value.
* @return A helper class for a delayed check for finite values,
* to be used as the `operation` in a `DelayedUnaryIsometricOperation`.
*/
template<bool pass_ = true, typename Value_ = double>
DelayedUnaryIsometricSpecialCompare<SpecialCompareOperation::ISFINITE, pass_, Value_> make_DelayedUnaryIsometricIsfinite() {
return DelayedUnaryIsometricSpecialCompare<SpecialCompareOperation::ISFINITE, pass_, Value_>();
}

}

#endif
130 changes: 130 additions & 0 deletions include/tatami/isometric/unary/substitute_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,136 @@ DelayedUnaryIsometricSubstituteVector<CompareOperation::NOT_EQUAL, Value_, Vecto
return DelayedUnaryIsometricSubstituteVector<CompareOperation::NOT_EQUAL, Value_, Vector_>(std::move(compared), std::move(substitute), by_row);
}

/**
* @cond
*/
template<SpecialCompareOperation op_, bool pass_, typename Value_>
bool delayed_special_substitute_is_sparse(Value_ substitute) {
return !delayed_special_compare<op_, pass_, Value_>(0) || substitute == 0;
}

template<SpecialCompareOperation op_, bool pass_, typename Value_>
void delayed_special_substitute_run(Value_& val, Value_ substitute) {
if (delayed_special_compare<op_, pass_, Value_>(val)) {
val = substitute;
}
}

template<SpecialCompareOperation op_, bool pass_, typename Value_, typename Index_>
void delayed_special_substitute_run_simple(Value_* buffer, Index_ length, Value_ substitute) {
for (Index_ i = 0; i < length; ++i) {
delayed_special_substitute_run<op_, pass_, Value_>(buffer[i], substitute);
}
}
/**
* @endcond
*/

/**
* @brief Delayed special value substitution.
*
* This should be used as the `Operation_` in the `DelayedUnaryIsometricOperation` class.
*
* @tparam op_ The special comparison operation.
* @tparam pass_ Whether to perform the substitution if the special comparison is true.
* Otherwise the substitution is only performed if the comparison is false.
* @tparam Value_ Type of the data value.
*/
template<SpecialCompareOperation op_, bool pass_, typename Value_ = double>
class DelayedUnaryIsometricSpecialSubstitute {
public:
/**
* @param substitute Scalar to substitute into the matrix for every element where the special comparison is true (if `pass_ = true`) or false (otherwise).
*/
DelayedUnaryIsometricSpecialSubstitute(Value_ substitute) : my_substitute(substitute) {
my_sparse = delayed_special_substitute_is_sparse<op_, pass_, Value_>(my_substitute);
}

private:
Value_ my_substitute;
bool my_sparse;

public:
/**
* @cond
*/
static constexpr bool is_basic = false;

bool is_sparse() const {
return my_sparse;
}
/**
* @endcond
*/

public:
/**
* @cond
*/
template<typename Index_>
void dense(bool, Index_, Index_, Index_ length, Value_* buffer) const {
delayed_special_substitute_run_simple<op_, pass_, Value_>(buffer, length, my_substitute);
}

template<typename Index_>
void dense(bool, Index_, const std::vector<Index_>& indices, Value_* buffer) const {
delayed_special_substitute_run_simple<op_, pass_, Value_>(buffer, static_cast<Index_>(indices.size()), my_substitute);
}

template<typename Index_>
void sparse(bool, Index_, Index_ number, Value_* buffer, const Index_*) const {
delayed_special_substitute_run_simple<op_, pass_, Value_>(buffer, number, my_substitute);
}

template<typename Index_>
Value_ fill(bool, Index_) const {
if (my_sparse) {
return 0;
} else {
return my_substitute;
}
}
/**
* @endcond
*/
};

/**
* @tparam pass_ Whether to perform the substitution if the matrix value is NaN.
* If false, the substitution is performed if the matrix value is not NaN.
* @tparam Value_ Type of the data value.
* @return A helper class for a delayed NaN check,
* to be used as the `operation` in a `DelayedUnaryIsometricOperation`.
*/
template<bool pass_ = true, typename Value_ = double>
DelayedUnaryIsometricSpecialSubstitute<SpecialCompareOperation::ISNAN, pass_, Value_> make_DelayedUnaryIsometricSubstituteIsnan(Value_ substitute) {
return DelayedUnaryIsometricSpecialSubstitute<SpecialCompareOperation::ISNAN, pass_, Value_>(substitute);
}

/**
* @tparam pass_ Whether to return truthy if the matrix value is infinite.
* If false, the substitution is performed if the matrix value is not infinite.
* @tparam Value_ Type of the data value.
* @return A helper class for a delayed check for infinity (positive or negative),
* to be used as the `operation` in a `DelayedUnaryIsometricOperation`.
*/
template<bool pass_ = true, typename Value_ = double>
DelayedUnaryIsometricSpecialSubstitute<SpecialCompareOperation::ISINF, pass_, Value_> make_DelayedUnaryIsometricSubstituteIsinf(Value_ substitute) {
return DelayedUnaryIsometricSpecialSubstitute<SpecialCompareOperation::ISINF, pass_, Value_>(substitute);
}

/**
* @tparam pass_ Whether to return truthy if the matrix value is finite.
* If false, the substitution is performed if the matrix value is not finite.
* @tparam Value_ Type of the data value.
* @return A helper class for a delayed check for finite values,
* to be used as the `operation` in a `DelayedUnaryIsometricOperation`.
*/
template<bool pass_ = true, typename Value_ = double>
DelayedUnaryIsometricSpecialSubstitute<SpecialCompareOperation::ISFINITE, pass_, Value_> make_DelayedUnaryIsometricSubstituteIsfinite(Value_ substitute) {
return DelayedUnaryIsometricSpecialSubstitute<SpecialCompareOperation::ISFINITE, pass_, Value_>(substitute);
}

}

#endif
Loading
Loading