Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZODB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
ZODB
Commits
012e6b5b
Commit
012e6b5b
authored
Jun 25, 2002
by
Tim Peters
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Negative weights behave as documented now for weightedUnion and
weightedIntersection.
parent
d9b60aaa
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
56 additions
and
28 deletions
+56
-28
src/BTrees/Interfaces.py
src/BTrees/Interfaces.py
+0
-6
src/BTrees/SetOpTemplate.c
src/BTrees/SetOpTemplate.c
+54
-20
src/BTrees/tests/testSetOps.py
src/BTrees/tests/testSetOps.py
+2
-2
No files found.
src/BTrees/Interfaces.py
View file @
012e6b5b
...
@@ -314,9 +314,6 @@ class IIMerge(IMerge):
...
@@ -314,9 +314,6 @@ class IIMerge(IMerge):
1 if the key is in c2 and c2 is a set
1 if the key is in c2 and c2 is a set
c2[key] if the key is in c2 and c2 is a mapping
c2[key] if the key is in c2 and c2 is a mapping
XXX All of the above is wrong if either weight is negative. I think
XXX that's a bug in the implementation and will fix it.
Note that c1 and c2 must be collections.
Note that c1 and c2 must be collections.
"""
"""
...
@@ -348,9 +345,6 @@ class IIMerge(IMerge):
...
@@ -348,9 +345,6 @@ class IIMerge(IMerge):
v2 is 1 if c2 is a set
v2 is 1 if c2 is a set
c2[key] if c2 is a mapping
c2[key] if c2 is a mapping
XXX All of the above is wrong if either weight is negative. I think
XXX that's a bug in the implementation and will fix it.
Note that c1 and c2 must be collections.
Note that c1 and c2 must be collections.
"""
"""
...
...
src/BTrees/SetOpTemplate.c
View file @
012e6b5b
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
Set operations
Set operations
****************************************************************************/
****************************************************************************/
#define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.2
6 2002/06/25 22:02:27
tim_one Exp $\n"
#define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.2
7 2002/06/25 22:46:42
tim_one Exp $\n"
#ifdef INTSET_H
#ifdef INTSET_H
static
int
static
int
...
@@ -198,8 +198,36 @@ copyRemaining(Bucket *r, SetIteration *i, int merge, int w)
...
@@ -198,8 +198,36 @@ copyRemaining(Bucket *r, SetIteration *i, int merge, int w)
return
0
;
return
0
;
}
}
/* This is the workhorse for all set merge operations: the weighted and
* unweighted flavors of union and intersection, and set difference. The
* algorithm is conceptually simple but the code is complicated due to all
* the options.
*
* s1, s2
* The input collections to be merged.
*
* usevalues1, usevalues2
* Booleans. In the output, should values from s1 (or s2) be used? This
* only makes sense when an operation intends to support mapping outputs;
* these should both be false for operations that want pure set outputs.
*
* w1, w2
* If usevalues1(2) are true, these are the weights to apply to the
* input values.
*
* c1
* Boolean. Should keys that appear in c1 but not c2 appear in the output?
* c12
* Boolean. Should keys that appear in both inputs appear in the output?
* c2
* Boolean. Should keys that appear in c2 but not c1 appear in the output?
*
* Returns NULL if error, else a Set or Bucket, depending on whether a set or
* mapping was requested.
*/
static
PyObject
*
static
PyObject
*
set_operation
(
PyObject
*
s1
,
PyObject
*
s2
,
set_operation
(
PyObject
*
s1
,
PyObject
*
s2
,
int
usevalues1
,
int
usevalues2
,
int
w1
,
int
w2
,
int
w1
,
int
w2
,
int
c1
,
int
c12
,
int
c2
)
int
c1
,
int
c12
,
int
c2
)
{
{
...
@@ -207,8 +235,8 @@ set_operation(PyObject *s1, PyObject *s2,
...
@@ -207,8 +235,8 @@ set_operation(PyObject *s1, PyObject *s2,
SetIteration
i1
=
{
0
,
0
,
0
},
i2
=
{
0
,
0
,
0
};
SetIteration
i1
=
{
0
,
0
,
0
},
i2
=
{
0
,
0
,
0
};
int
cmp
,
merge
;
int
cmp
,
merge
;
if
(
initSetIteration
(
&
i1
,
s1
,
w1
>=
0
)
<
0
)
goto
err
;
if
(
initSetIteration
(
&
i1
,
s1
,
usevalues1
)
<
0
)
goto
err
;
if
(
initSetIteration
(
&
i2
,
s2
,
w2
>=
0
)
<
0
)
goto
err
;
if
(
initSetIteration
(
&
i2
,
s2
,
usevalues2
)
<
0
)
goto
err
;
merge
=
i1
.
usesValue
|
i2
.
usesValue
;
merge
=
i1
.
usesValue
|
i2
.
usesValue
;
if
(
merge
)
if
(
merge
)
...
@@ -336,14 +364,16 @@ difference_m(PyObject *ignored, PyObject *args)
...
@@ -336,14 +364,16 @@ difference_m(PyObject *ignored, PyObject *args)
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO"
,
&
o1
,
&
o2
))
return
NULL
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO"
,
&
o1
,
&
o2
))
return
NULL
;
if
(
o1
==
Py_None
||
o2
==
Py_None
)
if
(
o1
==
Py_None
||
o2
==
Py_None
)
{
{
/* difference(None, X) -> None; difference(X, None) -> X */
/* difference(None, X) -> None; difference(X, None) -> X */
Py_INCREF
(
o1
);
Py_INCREF
(
o1
);
return
o1
;
return
o1
;
}
}
return
set_operation
(
o1
,
o2
,
1
,
-
1
,
1
,
0
,
0
);
return
set_operation
(
o1
,
o2
,
1
,
0
,
/* preserve values from o1, ignore o2's */
1
,
0
,
/* o1's values multiplied by 1 */
1
,
0
,
0
);
/* take only keys unique to o1 */
}
}
static
PyObject
*
static
PyObject
*
...
@@ -358,13 +388,15 @@ union_m(PyObject *ignored, PyObject *args)
...
@@ -358,13 +388,15 @@ union_m(PyObject *ignored, PyObject *args)
Py_INCREF
(
o2
);
Py_INCREF
(
o2
);
return
o2
;
return
o2
;
}
}
else
if
(
o2
==
Py_None
)
else
if
(
o2
==
Py_None
)
{
{
Py_INCREF
(
o1
);
Py_INCREF
(
o1
);
return
o1
;
return
o1
;
}
}
return
set_operation
(
o1
,
o2
,
-
1
,
-
1
,
1
,
1
,
1
);
return
set_operation
(
o1
,
o2
,
0
,
0
,
/* ignore values in both */
1
,
1
,
/* the weights are irrelevant */
1
,
1
,
1
);
/* take all keys */
}
}
static
PyObject
*
static
PyObject
*
...
@@ -374,18 +406,20 @@ intersection_m(PyObject *ignored, PyObject *args)
...
@@ -374,18 +406,20 @@ intersection_m(PyObject *ignored, PyObject *args)
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO"
,
&
o1
,
&
o2
))
return
NULL
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO"
,
&
o1
,
&
o2
))
return
NULL
;
if
(
o1
==
Py_None
)
if
(
o1
==
Py_None
)
{
{
Py_INCREF
(
o2
);
Py_INCREF
(
o2
);
return
o2
;
return
o2
;
}
}
else
if
(
o2
==
Py_None
)
else
if
(
o2
==
Py_None
)
{
{
Py_INCREF
(
o1
);
Py_INCREF
(
o1
);
return
o1
;
return
o1
;
}
}
return
set_operation
(
o1
,
o2
,
-
1
,
-
1
,
0
,
1
,
0
);
return
set_operation
(
o1
,
o2
,
0
,
0
,
/* ignore values in both */
1
,
1
,
/* the weights are irrelevant */
0
,
1
,
0
);
/* take only keys common to both */
}
}
#ifdef MERGE
#ifdef MERGE
...
@@ -394,16 +428,16 @@ static PyObject *
...
@@ -394,16 +428,16 @@ static PyObject *
wunion_m
(
PyObject
*
ignored
,
PyObject
*
args
)
wunion_m
(
PyObject
*
ignored
,
PyObject
*
args
)
{
{
PyObject
*
o1
,
*
o2
;
PyObject
*
o1
,
*
o2
;
int
w1
=
1
,
w2
=
1
;
int
w1
=
1
,
w2
=
1
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO|ii"
,
&
o1
,
&
o2
,
&
w1
,
&
w2
))
return
NULL
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO|ii"
,
&
o1
,
&
o2
,
&
w1
,
&
w2
))
return
NULL
;
if
(
o1
==
Py_None
)
if
(
o1
==
Py_None
)
return
Py_BuildValue
(
"iO"
,
(
o2
==
Py_None
?
0
:
w2
),
o2
);
return
Py_BuildValue
(
"iO"
,
(
o2
==
Py_None
?
0
:
w2
),
o2
);
else
if
(
o2
==
Py_None
)
else
if
(
o2
==
Py_None
)
return
Py_BuildValue
(
"iO"
,
w1
,
o1
);
return
Py_BuildValue
(
"iO"
,
w1
,
o1
);
o1
=
set_operation
(
o1
,
o2
,
w1
,
w2
,
1
,
1
,
1
);
o1
=
set_operation
(
o1
,
o2
,
1
,
1
,
w1
,
w2
,
1
,
1
,
1
);
if
(
o1
)
ASSIGN
(
o1
,
Py_BuildValue
(
"iO"
,
1
,
o1
));
if
(
o1
)
ASSIGN
(
o1
,
Py_BuildValue
(
"iO"
,
1
,
o1
));
return
o1
;
return
o1
;
...
@@ -413,16 +447,16 @@ static PyObject *
...
@@ -413,16 +447,16 @@ static PyObject *
wintersection_m
(
PyObject
*
ignored
,
PyObject
*
args
)
wintersection_m
(
PyObject
*
ignored
,
PyObject
*
args
)
{
{
PyObject
*
o1
,
*
o2
;
PyObject
*
o1
,
*
o2
;
int
w1
=
1
,
w2
=
1
;
int
w1
=
1
,
w2
=
1
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO|ii"
,
&
o1
,
&
o2
,
&
w1
,
&
w2
))
return
NULL
;
UNLESS
(
PyArg_ParseTuple
(
args
,
"OO|ii"
,
&
o1
,
&
o2
,
&
w1
,
&
w2
))
return
NULL
;
if
(
o1
==
Py_None
)
if
(
o1
==
Py_None
)
return
Py_BuildValue
(
"iO"
,
(
o2
==
Py_None
?
0
:
w2
),
o2
);
return
Py_BuildValue
(
"iO"
,
(
o2
==
Py_None
?
0
:
w2
),
o2
);
else
if
(
o2
==
Py_None
)
else
if
(
o2
==
Py_None
)
return
Py_BuildValue
(
"iO"
,
w1
,
o1
);
return
Py_BuildValue
(
"iO"
,
w1
,
o1
);
o1
=
set_operation
(
o1
,
o2
,
w1
,
w2
,
0
,
1
,
0
);
o1
=
set_operation
(
o1
,
o2
,
1
,
1
,
w1
,
w2
,
0
,
1
,
0
);
if
(
o1
)
if
(
o1
)
ASSIGN
(
o1
,
Py_BuildValue
(
"iO"
,
ASSIGN
(
o1
,
Py_BuildValue
(
"iO"
,
((
o1
->
ob_type
==
(
PyTypeObject
*
)(
&
SetType
))
?
w2
+
w1
:
1
),
((
o1
->
ob_type
==
(
PyTypeObject
*
)(
&
SetType
))
?
w2
+
w1
:
1
),
...
...
src/BTrees/tests/testSetOps.py
View file @
012e6b5b
...
@@ -339,8 +339,8 @@ class Weighted(TestCase):
...
@@ -339,8 +339,8 @@ class Weighted(TestCase):
self
.
emptys
=
[
make
([])
for
make
in
self
.
builders
]
self
.
emptys
=
[
make
([])
for
make
in
self
.
builders
]
weights
=
[]
weights
=
[]
for
w1
in
0
,
1
,
7
:
# -3, -1, 0, 1, 7: XXX negative weights buggy
for
w1
in
-
3
,
-
1
,
0
,
1
,
7
:
for
w2
in
0
,
1
,
7
:
# -3, -1, 0, 1, 7: XXX negative weights buggy
for
w2
in
-
3
,
-
1
,
0
,
1
,
7
:
weights
.
append
((
w1
,
w2
))
weights
.
append
((
w1
,
w2
))
self
.
weights
=
weights
self
.
weights
=
weights
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment