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

Merge pull request #739 from Daetalus/min_max

Min max
parents 22759d1a c4260dbc
...@@ -145,61 +145,90 @@ extern "C" Box* any(Box* container) { ...@@ -145,61 +145,90 @@ extern "C" Box* any(Box* container) {
return boxBool(false); 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); assert(args->cls == tuple_cls);
if (kwargs)
assert(kwargs->cls == dict_cls);
Box* minElement; Box* key_func = nullptr;
Box* extremElement;
Box* container; 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) { if (args->size() == 0) {
minElement = nullptr; extremElement = nullptr;
extremVal = nullptr;
container = arg0; container = arg0;
} else { } 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; container = args;
} }
Box* curVal = nullptr;
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
if (!minElement) { if (key_func != NULL) {
minElement = e; 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 { } else {
int r = PyObject_RichCompareBool(minElement, e, Py_GT); if (!extremElement) {
extremVal = e;
extremElement = e;
continue;
}
curVal = e;
}
int r = PyObject_RichCompareBool(curVal, extremVal, opid);
if (r == -1) if (r == -1)
throwCAPIException(); throwCAPIException();
if (r) if (r) {
minElement = e; 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) { if (!minElement) {
raiseExcHelper(ValueError, "min() arg is an empty sequence"); raiseExcHelper(ValueError, "min() arg is an empty sequence");
} }
return minElement; return minElement;
} }
extern "C" Box* max(Box* arg0, BoxedTuple* args) { extern "C" Box* max(Box* arg0, BoxedTuple* args, BoxedDict* kwargs) {
assert(args->cls == tuple_cls); if (arg0 == None && args->size() == 0) {
raiseExcHelper(TypeError, "max expected 1 arguments, got 0");
Box* maxElement;
Box* container;
if (args->size() == 0) {
maxElement = nullptr;
container = arg0;
} else {
maxElement = arg0;
container = args;
} }
for (Box* e : container->pyElements()) { Box* maxElement = min_max(arg0, args, kwargs, Py_GT);
if (!maxElement) {
maxElement = e;
} else {
int r = PyObject_RichCompareBool(maxElement, e, Py_LT);
if (r == -1)
throwCAPIException();
if (r)
maxElement = e;
}
}
if (!maxElement) { if (!maxElement) {
raiseExcHelper(ValueError, "max() arg is an empty sequence"); raiseExcHelper(ValueError, "max() arg is an empty sequence");
...@@ -1170,10 +1199,10 @@ void setupBuiltins() { ...@@ -1170,10 +1199,10 @@ void setupBuiltins() {
builtins_module->giveAttr("oct", builtins_module->giveAttr("oct",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)octFunc, UNKNOWN, 1), "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); 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("max", max_obj);
builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod( builtins_module->giveAttr("next", new BoxedBuiltinFunctionOrMethod(
......
...@@ -3450,8 +3450,8 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3450,8 +3450,8 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
for (int i = 0; i < paramspec.num_args - paramspec.num_defaults; i++) { for (int i = 0; i < paramspec.num_args - paramspec.num_defaults; i++) {
if (params_filled[i]) if (params_filled[i])
continue; continue;
// TODO not right error message raiseExcHelper(TypeError, "%s() takes exactly %d arguments (%d given)", func_name, paramspec.num_args,
raiseExcHelper(TypeError, "%s() did not get a value for positional argument %d", func_name, i); 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++) { 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) ...@@ -16,6 +16,130 @@ print min(1, 2)
print max(range(5)) print max(range(5))
print min(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]: for x in [float("inf"), math.pi]:
print x, math.isinf(x), math.fabs(x), math.ceil(x), math.log(x), math.log10(x) 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