LSST Applications g180d380827+0f66a164bb,g2079a07aa2+86d27d4dc4,g2305ad1205+7d304bc7a0,g29320951ab+500695df56,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g33d1c0ed96+0e5473021a,g3a166c0a6a+0e5473021a,g3ddfee87b4+e42ea45bea,g48712c4677+36a86eeaa5,g487adcacf7+2dd8f347ac,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+c70619cc9d,g5a732f18d5+53520f316c,g5ea96fc03c+341ea1ce94,g64a986408d+f7cd9c7162,g858d7b2824+f7cd9c7162,g8a8a8dda67+585e252eca,g99cad8db69+469ab8c039,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+c92fc63c7e,gbd866b1f37+f7cd9c7162,gc120e1dc64+02c66aa596,gc28159a63d+0e5473021a,gc3e9b769f7+b0068a2d9f,gcf0d15dbbd+e42ea45bea,gdaeeff99f8+f9a426f77a,ge6526c86ff+84383d05b3,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gff1a9f87cc+f7cd9c7162,w.2024.17
LSST Data Management Base Package
Loading...
Searching...
No Matches
_rangeSet.cc
Go to the documentation of this file.
1/*
2 * This file is part of sphgeom.
3 *
4 * Developed for the LSST Data Management System.
5 * This product includes software developed by the LSST Project
6 * (http://www.lsst.org).
7 * See the COPYRIGHT file at the top-level directory of this distribution
8 * for details of code ownership.
9 *
10 * This software is dual licensed under the GNU General Public License and also
11 * under a 3-clause BSD license. Recipients may choose which of these licenses
12 * to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
13 * respectively. If you choose the GPL option then the following text applies
14 * (but note that there is still no warranty even if you opt for BSD instead):
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29#include "pybind11/pybind11.h"
30
31#include "lsst/sphgeom/python.h"
32
35
36namespace py = pybind11;
37using namespace pybind11::literals;
38
39namespace lsst {
40namespace sphgeom {
41
42namespace {
43
45uint64_t _uint64(py::handle const &obj) {
46 try {
47 return obj.cast<uint64_t>();
48 } catch (py::cast_error const &) {
49 throw py::value_error(
50 "RangeSet elements and range beginning and "
51 "end points must be non-negative integers "
52 "less than 2**64");
53 }
54}
55
58RangeSet makeRangeSet(py::iterable iterable) {
59 RangeSet rs;
60 for (py::handle item : iterable) {
61 PyObject *o = item.ptr();
62 if (PySequence_Check(o) && PySequence_Size(o) == 2) {
63 uint64_t first = _uint64(py::reinterpret_steal<py::object>(
64 PySequence_GetItem(o, 0)));
65 uint64_t last = _uint64(py::reinterpret_steal<py::object>(
66 PySequence_GetItem(o, 1)));
67 rs.insert(first, last);
68 } else {
69 rs.insert(_uint64(item));
70 }
71 }
72 return rs;
73}
74
76py::list ranges(RangeSet const &self) {
77 py::list list;
78 for (auto t : self) {
79 list.append(py::make_tuple(py::int_(std::get<0>(t)),
80 py::int_(std::get<1>(t))));
81 }
82 return list;
83}
84
85// TODO: In C++, the end-point of a range containing 2**64 - 1 is 0, because
86// unsigned integer arithmetic is modular, and 2**64 does not fit in a
87// uint64_t. In Python, it would perhaps be nicer to map between C++
88// range end-point values of 0 and the Python integer 2**64. Since this is
89// somewhat involved, it is left as future work.
90
91} // <anonymous>
92
93template <>
95 cls.def(py::init<>());
96 cls.def(py::init<uint64_t>(), "integer"_a);
97 cls.def(py::init([](uint64_t a, uint64_t b) {
98 return new RangeSet(a, b);
99 }),
100 "first"_a, "last"_a);
101 cls.def(py::init<RangeSet const &>(), "rangeSet"_a);
102 cls.def(py::init(
103 [](py::iterable iterable) {
104 return new RangeSet(makeRangeSet(iterable));
105 }),
106 "iterable"_a);
107 cls.def("__eq__", &RangeSet::operator==, py::is_operator());
108 cls.def("__ne__", &RangeSet::operator!=, py::is_operator());
109
110 cls.def("insert", (void (RangeSet::*)(uint64_t)) & RangeSet::insert,
111 "integer"_a);
112 cls.def("insert",
113 (void (RangeSet::*)(uint64_t, uint64_t)) & RangeSet::insert,
114 "first"_a, "last"_a);
115 cls.def("erase", (void (RangeSet::*)(uint64_t)) & RangeSet::erase,
116 "integer"_a);
117 cls.def("erase", (void (RangeSet::*)(uint64_t, uint64_t)) & RangeSet::erase,
118 "first"_a, "last"_a);
119
120 cls.def("complement", &RangeSet::complement);
121 cls.def("complemented", &RangeSet::complemented);
122 cls.def("intersection", &RangeSet::intersection, "rangeSet"_a);
123 // In C++, the set union function is named join because union is a keyword.
124 // Python does not suffer from the same restriction.
125 cls.def("union", &RangeSet::join, "rangeSet"_a);
126 cls.def("difference", &RangeSet::difference, "rangeSet"_a);
127 cls.def("symmetricDifference", &RangeSet::symmetricDifference,
128 "rangeSet"_a);
129 cls.def("__invert__", &RangeSet::operator~, py::is_operator());
130 cls.def("__and__", &RangeSet::operator&, py::is_operator());
131 cls.def("__or__", &RangeSet::operator|, py::is_operator());
132 cls.def("__sub__", &RangeSet::operator-, py::is_operator());
133 cls.def("__xor__", &RangeSet::operator^, py::is_operator());
134 cls.def("__iand__", &RangeSet::operator&=);
135 cls.def("__ior__", &RangeSet::operator|=);
136 cls.def("__isub__", &RangeSet::operator-=);
137 cls.def("__ixor__", &RangeSet::operator^=);
138
139 cls.def("__len__", &RangeSet::size);
140 cls.def("__getitem__", [](RangeSet const &self, py::int_ i) {
141 auto j = python::convertIndex(static_cast<ptrdiff_t>(self.size()), i);
142 return py::cast(self.begin()[j]);
143 });
144
145 cls.def("intersects",
146 (bool (RangeSet::*)(uint64_t) const) & RangeSet::intersects,
147 "integer"_a);
148 cls.def("intersects",
149 (bool (RangeSet::*)(uint64_t, uint64_t) const) &
151 "first"_a, "last"_a);
152 cls.def("intersects",
153 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::intersects,
154 "rangeSet"_a);
155
156 cls.def("contains",
157 (bool (RangeSet::*)(uint64_t) const) & RangeSet::contains,
158 "integer"_a);
159 cls.def("contains",
160 (bool (RangeSet::*)(uint64_t, uint64_t) const) & RangeSet::contains,
161 "first"_a, "last"_a);
162 cls.def("contains",
163 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::contains,
164 "rangeSet"_a);
165 cls.def("__contains__",
166 (bool (RangeSet::*)(uint64_t) const) & RangeSet::contains,
167 "integer"_a, py::is_operator());
168 cls.def("__contains__",
169 (bool (RangeSet::*)(uint64_t, uint64_t) const) & RangeSet::contains,
170 "first"_a, "last"_a, py::is_operator());
171 cls.def("__contains__",
172 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::contains,
173 "rangeSet"_a, py::is_operator());
174
175 cls.def("isWithin",
176 (bool (RangeSet::*)(uint64_t) const) & RangeSet::isWithin,
177 "integer"_a);
178 cls.def("isWithin",
179 (bool (RangeSet::*)(uint64_t, uint64_t) const) & RangeSet::isWithin,
180 "first"_a, "last"_a);
181 cls.def("isWithin",
182 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::isWithin,
183 "rangeSet"_a);
184
185 cls.def("isDisjointFrom",
186 (bool (RangeSet::*)(uint64_t) const) & RangeSet::isDisjointFrom,
187 "integer"_a);
188 cls.def("isDisjointFrom",
189 (bool (RangeSet::*)(uint64_t, uint64_t) const) &
191 "first"_a, "last"_a);
192 cls.def("isDisjointFrom",
193 (bool (RangeSet::*)(RangeSet const &) const) &
195 "rangeSet"_a);
196
197 cls.def("simplify", &RangeSet::simplify, "n"_a);
198 cls.def("simplified", &RangeSet::simplified, "n"_a);
199 cls.def("scale", &RangeSet::scale, "factor"_a);
200 cls.def("scaled", &RangeSet::scaled, "factor"_a);
201 cls.def("fill", &RangeSet::fill);
202 cls.def("clear", &RangeSet::clear);
203 cls.def("empty", &RangeSet::empty);
204 cls.def("full", &RangeSet::full);
205 cls.def("size", &RangeSet::size);
206 cls.def("cardinality", &RangeSet::cardinality);
207 // max_size() and swap() are omitted. The former is a C++ container
208 // requirement, and the latter doesn't seem relevant to Python.
209 cls.def("isValid", &RangeSet::cardinality);
210 cls.def("ranges", &ranges);
211
212 cls.def("__str__",
213 [](RangeSet const &self) { return py::str(ranges(self)); });
214 cls.def("__repr__", [](RangeSet const &self) {
215 return py::str("RangeSet({!s})").format(ranges(self));
216 });
217
218 cls.def("__reduce__", [cls](RangeSet const &self) {
219 return py::make_tuple(cls, py::make_tuple(ranges(self)));
220 });
221}
222
223} // sphgeom
224} // lsst
This file provides a type for representing integer sets.
table::Key< int > b
A RangeSet is a set of unsigned 64 bit integers.
Definition RangeSet.h:106
RangeSet intersection(RangeSet const &s) const
intersection returns the intersection of this set and s.
Definition RangeSet.cc:142
bool intersects(uint64_t u) const
Definition RangeSet.h:432
void clear()
clear removes all integers from this set.
Definition RangeSet.h:508
bool isWithin(uint64_t u) const
Definition RangeSet.h:452
void insert(uint64_t u)
Definition RangeSet.h:292
bool full() const
full checks whether all integers in the universe of range sets, [0, 2^64), are in this set.
Definition RangeSet.h:518
bool contains(uint64_t u) const
Definition RangeSet.h:442
RangeSet join(RangeSet const &s) const
join returns the union of this set and s.
Definition RangeSet.cc:152
RangeSet & scale(uint64_t i)
scale multiplies the endpoints of each range in this set by the given integer.
Definition RangeSet.cc:361
bool isDisjointFrom(uint64_t u) const
Definition RangeSet.h:462
RangeSet simplified(uint32_t n) const
simplified returns a simplified copy of this set.
Definition RangeSet.h:486
bool empty() const
empty checks whether there are any integers in this set.
Definition RangeSet.h:514
RangeSet scaled(uint64_t i) const
scaled returns a scaled copy of this set.
Definition RangeSet.h:501
RangeSet & complement()
complement replaces this set S with U ∖ S, where U is the universe of range sets, [0,...
Definition RangeSet.h:335
size_t size() const
size returns the number of ranges in this set.
Definition RangeSet.h:546
void fill()
fill adds all the unsigned 64 bit integers to this set.
Definition RangeSet.h:511
void erase(uint64_t u)
Definition RangeSet.h:313
RangeSet complemented() const
complemented returns a complemented copy of this set.
Definition RangeSet.h:338
RangeSet difference(RangeSet const &s) const
difference returns the difference between this set and s.
Definition RangeSet.cc:164
RangeSet & simplify(uint32_t n)
simplify simplifies this range set by "coarsening" its ranges.
Definition RangeSet.cc:315
uint64_t cardinality() const
cardinality returns the number of integers in this set.
Definition RangeSet.cc:307
RangeSet symmetricDifference(RangeSet const &s) const
symmetricDifference returns the symmetric difference of this set and s.
Definition RangeSet.cc:173
daf::base::PropertyList * list
Definition fits.cc:932
ptrdiff_t convertIndex(ptrdiff_t len, pybind11::int_ i)
Convert a Python index i over a sequence with length len to a non-negative (C++ style) index,...
Definition utils.h:47
void defineClass(Pybind11Class &cls)