Commit 4cd23054 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #739 from Daetalus/min_max

Min max
parents 22759d1a c4260dbc
......@@ -145,30 +145,77 @@ extern "C" Box* any(Box* container) {
return boxBool(false);
}
extern "C" Box* min(Box* arg0, BoxedTuple* args) {
Box* min_max(Box* arg0, BoxedTuple* args, BoxedDict* kwargs, int opid) {
assert(args->cls == tuple_cls);
if (kwargs)
assert(kwargs->cls == dict_cls);
Box* minElement;
Box* key_func = nullptr;
Box* extremElement;
Box* container;
Box* extremVal;
if (kwargs && kwargs->d.size()) {
static BoxedString* key_str = static_cast<BoxedString*>(PyString_InternFromString("key"));
auto it = kwargs->d.find(key_str);
if (it != kwargs->d.end() && kwargs->d.size() == 1) {
key_func = it->second;
} else {
if (opid == Py_LT)
raiseExcHelper(TypeError, "min() got an unexpected keyword argument");
else
raiseExcHelper(TypeError, "max() got an unexpected keyword argument");
}
}
if (args->size() == 0) {
minElement = nullptr;
extremElement = nullptr;
extremVal = nullptr;
container = arg0;
} else {
minElement = arg0;
extremElement = arg0;
if (key_func != NULL) {
extremVal = runtimeCall(key_func, ArgPassSpec(1), extremElement, NULL, NULL, NULL, NULL);
} else {
extremVal = extremElement;
}
container = args;
}
Box* curVal = nullptr;
for (Box* e : container->pyElements()) {
if (!minElement) {
minElement = e;
if (key_func != NULL) {
if (!extremElement) {
extremVal = runtimeCall(key_func, ArgPassSpec(1), e, NULL, NULL, NULL, NULL);
extremElement = e;
continue;
}
curVal = runtimeCall(key_func, ArgPassSpec(1), e, NULL, NULL, NULL, NULL);
} else {
int r = PyObject_RichCompareBool(minElement, e, Py_GT);
if (r == -1)
throwCAPIException();
if (r)
minElement = e;
if (!extremElement) {
extremVal = e;
extremElement = e;
continue;
}
curVal = e;
}
int r = PyObject_RichCompareBool(curVal, extremVal, opid);
if (r == -1)
throwCAPIException();
if (r) {
extremElement = e;
extremVal = curVal;
}
}
return extremElement;
}
extern "C" Box* min(Box* arg0, BoxedTuple* args, BoxedDict* kwargs) {
if (arg0 == None && args->size() == 0) {
raiseExcHelper(TypeError, "min expected 1 arguments, got 0");
}
Box* minElement = min_max(arg0, args, kwargs, Py_LT);
if (!minElement) {
raiseExcHelper(ValueError, "min() arg is an empty sequence");
......@@ -176,30 +223,12 @@ extern "C" Box* min(Box* arg0, BoxedTuple* args) {
return minElement;
}
extern "C" Box* max(Box* arg0, BoxedTuple* args) {
assert(args->cls == tuple_cls);
Box* maxElement;
Box* container;
if (args->size() == 0) {
maxElement = nullptr;
container = arg0;
} else {
maxElement = arg0;
container = args;
extern "C" Box* max(Box* arg0, BoxedTuple* args, BoxedDict* kwargs) {
if (arg0 == None && args->size() == 0) {
raiseExcHelper(TypeError, "max expected 1 arguments, got 0");
}
for (Box* e : container->pyElements()) {
if (!maxElement) {
maxElement = e;
} else {
int r = PyObject_RichCompareBool(maxElement, e, Py_LT);
if (r == -1)
throwCAPIException();
if (r)
maxElement = e;
}
}
Box* maxElement = min_max(arg0, args, kwargs, Py_GT);
if (!maxElement) {
raiseExcHelper(ValueError, "max() arg is an empty sequence");
......@@ -1170,10 +1199,10 @@ void setupBuiltins() {
builtins_module->giveAttr("oct",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)octFunc, UNKNOWN, 1), "oct"));
min_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)min, UNKNOWN, 1, 0, true, false), "min");
min_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)min, UNKNOWN, 1, 1, true, true), "min", { None });
builtins_module->giveAttr("min", min_obj);
max_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)max, UNKNOWN, 1, 0, true, false), "max");
max_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)max, UNKNOWN, 1, 1, true, true), "max", { None });
builtins_module->giveAttr("max", max_obj);
builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod(
......
......@@ -3450,8 +3450,8 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
for (int i = 0; i < paramspec.num_args - paramspec.num_defaults; i++) {
if (params_filled[i])
continue;
// TODO not right error message
raiseExcHelper(TypeError, "%s() did not get a value for positional argument %d", func_name, i);
raiseExcHelper(TypeError, "%s() takes exactly %d arguments (%d given)", func_name, paramspec.num_args,
argspec.num_args + argspec.num_keywords + varargs.size());
}
for (int arg_idx = paramspec.num_args - paramspec.num_defaults; arg_idx < paramspec.num_args; arg_idx++) {
......
......@@ -16,6 +16,130 @@ print min(1, 2)
print max(range(5))
print min(range(5))
print min(['aaa', 'bbb', 'c'])
print min(1, 2, 3)
print min(0.1, 1.4, 12.7)
print min('a', 'b', 'c')
print min('aaa', 'bbb', 'c')
print min('1', 2, 3, 'aa')
print min([1, 2, 3])
print min([0.1, 1.4, 12.7])
print min(['a', 'b', 'c'])
print min(['aaa', 'bbb', 'c'])
print min(['1', 2, 3, 'aa'])
try:
min(1)
except TypeError as e:
print e.message
try:
min()
except TypeError as e:
print e.message
try:
min([])
except ValueError as e:
print e.message
print max(1, 2, 3)
print max(0.1, 1.4, 12.7)
print max('a', 'b', 'c')
print max('aaa', 'bbb', 'c')
print max('1', 2, 3, 'aa')
print max([1, 2, 3])
print max([0.1, 1.4, 12.7])
print max(['a', 'b', 'c'])
print max(['aaa', 'bbb', 'c'])
print max(['1', 2, 3, 'aa'])
try:
max(1)
except TypeError as e:
print e.message
try:
max()
except TypeError as e:
print e.message
try:
max([])
except ValueError as e:
print e.message
# test with key function
lst = [2, 1, 3, 4]
print(min(lst, key=lambda x: x))
print(min(lst, key=lambda x: -x))
print(min(1, 2, 3, 4, key=lambda x: -x))
print(min(4, 3, 2, 1, key=lambda x: -x))
print(max(lst, key=lambda x: x))
print(max(lst, key=lambda x: -x))
print(max(1, 2, 3, 4, key=lambda x: -x))
print(max(4, 3, 2, 1, key=lambda x: -x))
print min([[1, 2], [3, 4], [9, 0]], key=lambda x: x[1])
print min(1.2, 6.3, 6.9, key=int)
print min("moon", "sun", "earth", key=len)
print max([[1, 2], [3, 4], [9, 0]], key=lambda x: x[1])
print max(1.2, 6.3, 6.9, key=int)
print max("moon", "sun", "earth", key=len)
try:
min(1, a=1)
except TypeError as e:
print e.message
try:
max(1, a=1)
except TypeError as e:
print e.message
try:
min(1, 2, key=lambda x, y: x+y)
except TypeError as e:
print e.message
try:
max(1, 2, key=lambda x, y: x+y)
except TypeError as e:
print e.message
try:
min([1], key=lambda x: x, extra_arg=1)
except TypeError:
print e.message
try:
max([1], key=lambda x: x, extra_arg=1)
except TypeError:
print e.message
class C(object):
def __init__(self, n):
self.n = n
def __lt__(self, rhs):
print "lt", self.n, rhs.n
return self.n < rhs.n
def __gt__(self, rhs):
print "gt", self.n, rhs.n
return self.n > rhs.n
def key(x):
print "key", x.n
return C(-x.n)
print min([C(1), C(3), C(2)], key=key).n
print max([C(1), C(3), C(2)], key=key).n
for x in [float("inf"), math.pi]:
print x, math.isinf(x), math.fabs(x), math.ceil(x), math.log(x), math.log10(x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment