LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros
@ 2008-03-11 21:11 Harvey Harrison
  2008-03-12  5:08 ` Andrew Morton
  2008-03-12 15:13 ` Michael Buesch
  0 siblings, 2 replies; 6+ messages in thread
From: Harvey Harrison @ 2008-03-11 21:11 UTC (permalink / raw)
  To: Andrew Morton
  Cc: LKML, Michael Buesch, Alan Cox, Jeff Garzik,
	Bartlomiej Zolnierkiewicz, Mauro Carvalho Chehab

Adds macros similar to min/max/min_t/max_t.

Also, change the variable names used in the min/max macros to
avoid shadowed variable warnings when min/max min_t/max_t are
nested.

clamp_val is useful when clamping to constants so all types are
taken from typeof() the first arg.

Small formatting changes to make all the macros have a similar
form.

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
---
Andrew, this is a rollup of my original patch already in -mm with
checkpatch warnings fixed up and one additional macro based on
limit_value found in the b43 driver, called clamp_val.

clamp_t is no longer used, but I introduce it anyway as some future
user may want to force the return type similar to how min_t/max_t
operate.

 include/linux/kernel.h |   66 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2df44e7..b9331ac 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -335,33 +335,63 @@ static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char *
 #endif /* __LITTLE_ENDIAN */
 
 /*
- * min()/max() macros that also do
+ * min()/max()/clamp() macros that also do
  * strict type-checking.. See the
  * "unnecessary" pointer comparison.
  */
-#define min(x,y) ({ \
-	typeof(x) _x = (x);	\
-	typeof(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x < _y ? _x : _y; })
-
-#define max(x,y) ({ \
-	typeof(x) _x = (x);	\
-	typeof(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x > _y ? _x : _y; })
+#define min(x, y) ({				\
+	typeof(x) _min1 = (x);			\
+	typeof(y) _min2 = (y);			\
+	(void) (&_min1 == &_min2);		\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({				\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	(void) (&_max1 == &_max2);		\
+	_max1 > _max2 ? _max1 : _max2; })
+
+#define clamp(val, min, max) ({			\
+	typeof(val) __val = (val);		\
+	typeof(min) __min = (min);		\
+	typeof(max) __max = (max);		\
+	(void) (&__val == &__min);		\
+	(void) (&__val == &__max);		\
+	__val = __val < __min ? __min: __val;	\
+	__val > __max ? __max: __val; })
+
+/*
+ * Useful when min and max are constants.
+ */
+#define clamp_val(val, min, max) ({		\
+	typeof(val) __val = (val);		\
+	typeof(val) __min = (min);		\
+	typeof(val) __max = (max);		\
+	__val = __val < __min ? __min: __val;	\
+	__val > __max ? __max: __val; })
 
 /*
  * ..and if you can't take the strict
  * types, you can specify one yourself.
  *
- * Or not use min/max at all, of course.
+ * Or not use min/max/clamp at all, of course.
  */
-#define min_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#define max_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
-
+#define min_t(type, x, y) ({			\
+	type __min1 = (x);			\
+	type __min2 = (y);			\
+	__min1 < __min2 ? __min1: __min2; })
+
+#define max_t(type, x, y) ({			\
+	type __max1 = (x);			\
+	type __max2 = (y);			\
+	__max1 > __max2 ? __max1: __max2; })
+
+#define clamp_t(type, val, min, max) ({		\
+	type __val = (val);			\
+	type __min = (min);			\
+	type __max = (max);			\
+	__val = __val < __min ? __min: __val;	\
+	__val > __max ? __max: __val; })
 
 /**
  * container_of - cast a member of a structure out to the containing structure
-- 
1.5.4.4.592.g32d4c



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros
  2008-03-11 21:11 [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros Harvey Harrison
@ 2008-03-12  5:08 ` Andrew Morton
  2008-03-12 15:13 ` Michael Buesch
  1 sibling, 0 replies; 6+ messages in thread
From: Andrew Morton @ 2008-03-12  5:08 UTC (permalink / raw)
  To: Harvey Harrison
  Cc: LKML, Michael Buesch, Alan Cox, Jeff Garzik,
	Bartlomiej Zolnierkiewicz, Mauro Carvalho Chehab

On Tue, 11 Mar 2008 14:11:34 -0700 Harvey Harrison <harvey.harrison@gmail.com> wrote:

> Adds macros similar to min/max/min_t/max_t.
> 
> Also, change the variable names used in the min/max macros to
> avoid shadowed variable warnings when min/max min_t/max_t are
> nested.
> 
> clamp_val is useful when clamping to constants so all types are
> taken from typeof() the first arg.
> 
> Small formatting changes to make all the macros have a similar
> form.
> 
> Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
> ---
> Andrew, this is a rollup of my original patch already in -mm with
> checkpatch warnings fixed up and one additional macro based on
> limit_value found in the b43 driver, called clamp_val.

Well, this is why I dislike replacement patches.  You don't know what
changed, and the replacement patch can fail to incproporate fixes from
third parties.

>  include/linux/kernel.h |   66 ++++++++++++++++++++++++++++++++++-------------
>  1 files changed, 48 insertions(+), 18 deletions(-)

And so it did.  You lost my patch which removes the clamp() implementation
from v4l.  Instead it seems that you put it into [2/6].  Which means that
this patch on its own will break the build, thus screwing up life for
git-bisect users.

Please don't screw up git-bisect users' lives.

> clamp_t is no longer used, but I introduce it anyway as some future
> user may want to force the return type similar to how min_t/max_t
> operate.

eh, just nuke it.

> 1.5.4.4.592.g32d4c

Is all this new infrastructure actually used?  We seem to be adding more
complexity than we're taking away.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros
  2008-03-11 21:11 [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros Harvey Harrison
  2008-03-12  5:08 ` Andrew Morton
@ 2008-03-12 15:13 ` Michael Buesch
  2008-03-12 16:54   ` Harvey Harrison
  1 sibling, 1 reply; 6+ messages in thread
From: Michael Buesch @ 2008-03-12 15:13 UTC (permalink / raw)
  To: Harvey Harrison
  Cc: Andrew Morton, LKML, Alan Cox, Jeff Garzik,
	Bartlomiej Zolnierkiewicz, Mauro Carvalho Chehab

On Tuesday 11 March 2008 22:11:34 Harvey Harrison wrote:
> Adds macros similar to min/max/min_t/max_t.
> 
> Also, change the variable names used in the min/max macros to
> avoid shadowed variable warnings when min/max min_t/max_t are
> nested.
> 
> clamp_val is useful when clamping to constants so all types are
> taken from typeof() the first arg.
> 
> Small formatting changes to make all the macros have a similar
> form.
> 
> Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
> ---
> Andrew, this is a rollup of my original patch already in -mm with
> checkpatch warnings fixed up and one additional macro based on
> limit_value found in the b43 driver, called clamp_val.
> 
> clamp_t is no longer used, but I introduce it anyway as some future
> user may want to force the return type similar to how min_t/max_t
> operate.
> 
>  include/linux/kernel.h |   66 ++++++++++++++++++++++++++++++++++-------------
>  1 files changed, 48 insertions(+), 18 deletions(-)
> 
> diff --git a/include/linux/kernel.h b/include/linux/kernel.h
> index 2df44e7..b9331ac 100644
> --- a/include/linux/kernel.h
> +++ b/include/linux/kernel.h
> @@ -335,33 +335,63 @@ static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char *
>  #endif /* __LITTLE_ENDIAN */
>  
>  /*
> - * min()/max() macros that also do
> + * min()/max()/clamp() macros that also do
>   * strict type-checking.. See the
>   * "unnecessary" pointer comparison.
>   */
> -#define min(x,y) ({ \
> -	typeof(x) _x = (x);	\
> -	typeof(y) _y = (y);	\
> -	(void) (&_x == &_y);		\
> -	_x < _y ? _x : _y; })
> -
> -#define max(x,y) ({ \
> -	typeof(x) _x = (x);	\
> -	typeof(y) _y = (y);	\
> -	(void) (&_x == &_y);		\
> -	_x > _y ? _x : _y; })
> +#define min(x, y) ({				\
> +	typeof(x) _min1 = (x);			\
> +	typeof(y) _min2 = (y);			\
> +	(void) (&_min1 == &_min2);		\
> +	_min1 < _min2 ? _min1 : _min2; })
> +
> +#define max(x, y) ({				\
> +	typeof(x) _max1 = (x);			\
> +	typeof(y) _max2 = (y);			\
> +	(void) (&_max1 == &_max2);		\
> +	_max1 > _max2 ? _max1 : _max2; })
> +
> +#define clamp(val, min, max) ({			\
> +	typeof(val) __val = (val);		\
> +	typeof(min) __min = (min);		\
> +	typeof(max) __max = (max);		\
> +	(void) (&__val == &__min);		\
> +	(void) (&__val == &__max);		\
> +	__val = __val < __min ? __min: __val;	\
> +	__val > __max ? __max: __val; })
> +
> +/*
> + * Useful when min and max are constants.
> + */
> +#define clamp_val(val, min, max) ({		\

So why not call it clamp_const()?
One could even use __builtin_constant_p() and make clamp() use
either clamp_const() or clamp_nonconst() from above automagically.
I'd prefer that.

> +	typeof(val) __val = (val);		\
> +	typeof(val) __min = (min);		\
> +	typeof(val) __max = (max);		\
> +	__val = __val < __min ? __min: __val;	\
> +	__val > __max ? __max: __val; })
>  
>  /*
>   * ..and if you can't take the strict
>   * types, you can specify one yourself.
>   *
> - * Or not use min/max at all, of course.
> + * Or not use min/max/clamp at all, of course.
>   */
> -#define min_t(type,x,y) \
> -	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
> -#define max_t(type,x,y) \
> -	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
> -
> +#define min_t(type, x, y) ({			\
> +	type __min1 = (x);			\
> +	type __min2 = (y);			\
> +	__min1 < __min2 ? __min1: __min2; })
> +
> +#define max_t(type, x, y) ({			\
> +	type __max1 = (x);			\
> +	type __max2 = (y);			\
> +	__max1 > __max2 ? __max1: __max2; })
> +
> +#define clamp_t(type, val, min, max) ({		\
> +	type __val = (val);			\
> +	type __min = (min);			\
> +	type __max = (max);			\
> +	__val = __val < __min ? __min: __val;	\
> +	__val > __max ? __max: __val; })
>  
>  /**
>   * container_of - cast a member of a structure out to the containing structure



-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros
  2008-03-12 15:13 ` Michael Buesch
@ 2008-03-12 16:54   ` Harvey Harrison
  2008-03-12 17:20     ` Michael Buesch
  0 siblings, 1 reply; 6+ messages in thread
From: Harvey Harrison @ 2008-03-12 16:54 UTC (permalink / raw)
  To: Michael Buesch
  Cc: Andrew Morton, LKML, Alan Cox, Jeff Garzik,
	Bartlomiej Zolnierkiewicz, Mauro Carvalho Chehab

On Wed, 2008-03-12 at 16:13 +0100, Michael Buesch wrote:
> So why not call it clamp_const()?
> One could even use __builtin_constant_p() and make clamp() use
> either clamp_const() or clamp_nonconst() from above automagically.
> I'd prefer that.

Did you mean something like this?  No more clamp_val, just clamp and
clamp_t.  clamp_t forces all the types, clamp looks at the min and max
args, and if they are constants, uses the type of val instead.  If not
a constant, the strict typechecking is done.

From: Harvey Harrison <harvey.harrison@gmail.com>
Subject: [PATCH] kernel: add clamp(), clamp_t() macros

Adds macros similar to min/max/min_t/max_t.

Also, change the variable names used in the min/max macros to
avoid shadowed variable warnings when min/max min_t/max_t are
nested.

Small formatting changes to make all the macros have a similar
form.

Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
---
 include/linux/kernel.h |   68 +++++++++++++++++++++++++++++++++++------------
 1 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2df44e7..0d4cb5f 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -335,33 +335,65 @@ static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char *
 #endif /* __LITTLE_ENDIAN */
 
 /*
- * min()/max() macros that also do
+ * min()/max()/clamp() macros that also do
  * strict type-checking.. See the
  * "unnecessary" pointer comparison.
  */
-#define min(x,y) ({ \
-	typeof(x) _x = (x);	\
-	typeof(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x < _y ? _x : _y; })
-
-#define max(x,y) ({ \
-	typeof(x) _x = (x);	\
-	typeof(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x > _y ? _x : _y; })
+#define min(x, y) ({				\
+	typeof(x) _min1 = (x);			\
+	typeof(y) _min2 = (y);			\
+	(void) (&_min1 == &_min2);		\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({				\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	(void) (&_max1 == &_max2);		\
+	_max1 > _max2 ? _max1 : _max2; })
+
+#define clamp(val, min, max) ({				\
+	typeof(val) __val = (val);			\
+							\
+	if (__builtin_constant_p(min)) {		\
+		typeof(val) __min = (min);		\
+		__val = __val < __min ? __min: __val;	\
+	} else {					\
+		typeof(min) __min = (min);		\
+		(void) (&__val == &__min);		\
+		__val = __val < __min ? __min: __val;	\
+	}						\
+							\
+	if (__builtin_constant_p(max)) {		\
+		typeof(val) __max = (max);		\
+		__val > __max ? __max: __val;		\
+	} else {					\
+		typeof(max) __max = (max);		\
+		(void) (&__val == &__max);		\
+		__val > __max ? __max: __val;		\
+	} })
 
 /*
  * ..and if you can't take the strict
  * types, you can specify one yourself.
  *
- * Or not use min/max at all, of course.
+ * Or not use min/max/clamp at all, of course.
  */
-#define min_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#define max_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
-
+#define min_t(type, x, y) ({			\
+	type __min1 = (x);			\
+	type __min2 = (y);			\
+	__min1 < __min2 ? __min1: __min2; })
+
+#define max_t(type, x, y) ({			\
+	type __max1 = (x);			\
+	type __max2 = (y);			\
+	__max1 > __max2 ? __max1: __max2; })
+
+#define clamp_t(type, val, min, max) ({		\
+	type __val = (val);			\
+	type __min = (min);			\
+	type __max = (max);			\
+	__val = __val < __min ? __min: __val;	\
+	__val > __max ? __max: __val; })
 
 /**
  * container_of - cast a member of a structure out to the containing structure
-- 
1.5.4.4.592.g32d4c




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros
  2008-03-12 16:54   ` Harvey Harrison
@ 2008-03-12 17:20     ` Michael Buesch
  2008-03-12 17:34       ` Harvey Harrison
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Buesch @ 2008-03-12 17:20 UTC (permalink / raw)
  To: Harvey Harrison
  Cc: Andrew Morton, LKML, Alan Cox, Jeff Garzik,
	Bartlomiej Zolnierkiewicz, Mauro Carvalho Chehab

On Wednesday 12 March 2008 17:54:26 Harvey Harrison wrote:
> On Wed, 2008-03-12 at 16:13 +0100, Michael Buesch wrote:
> > So why not call it clamp_const()?
> > One could even use __builtin_constant_p() and make clamp() use
> > either clamp_const() or clamp_nonconst() from above automagically.
> > I'd prefer that.
> 
> Did you mean something like this?  No more clamp_val, just clamp and
> clamp_t.  clamp_t forces all the types, clamp looks at the min and max
> args, and if they are constants, uses the type of val instead.  If not
> a constant, the strict typechecking is done.

> +#define clamp(val, min, max) ({				\
> +	typeof(val) __val = (val);			\
> +							\
> +	if (__builtin_constant_p(min)) {		\
> +		typeof(val) __min = (min);		\
> +		__val = __val < __min ? __min: __val;	\
> +	} else {					\
> +		typeof(min) __min = (min);		\
> +		(void) (&__val == &__min);		\
> +		__val = __val < __min ? __min: __val;	\
> +	}						\
> +							\
> +	if (__builtin_constant_p(max)) {		\
> +		typeof(val) __max = (max);		\
> +		__val > __max ? __max: __val;		\
> +	} else {					\
> +		typeof(max) __max = (max);		\
> +		(void) (&__val == &__max);		\
> +		__val > __max ? __max: __val;		\
> +	} })

Yeah, something like that.
Does returning of the value work over an indentation level, too?
I dunno this detail of the language.
But I'd prefer the following for readability anyway:

+       if (__builtin_constant_p(max)) {                \
+               typeof(val) __max = (max);              \
+               __val = __val > __max ? __max: __val;           \
+       } else {                                        \
+               typeof(max) __max = (max);              \
+               (void) (&__val == &__max);              \
+               __val = __val > __max ? __max: __val;           \
+       }
+	__val; })

Probably you can also only put the pointer check into the constant check:

+#define clamp(val, min, max) ({                \
+       typeof(val) __val = (val);              \
+       typeof(min) __min = (min);              \
+       typeof(max) __max = (max);              \
+       if (!__builtin_constant_p(min))         \
+               (void) (&__val == &__min);      \
+       __val = __val < __min ? __min: __val;   \
+       if (!__builtin_constant_p(max))         \
+               (void) (&__val == &__max);      \
+       __val = __val > __max ? __max: __val;   \
+       __val; })

But it seems that this evaluates the arguments twice, so my idea turns out
to be not too good anyway. hm..

-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros
  2008-03-12 17:20     ` Michael Buesch
@ 2008-03-12 17:34       ` Harvey Harrison
  0 siblings, 0 replies; 6+ messages in thread
From: Harvey Harrison @ 2008-03-12 17:34 UTC (permalink / raw)
  To: Michael Buesch
  Cc: Andrew Morton, LKML, Alan Cox, Jeff Garzik,
	Bartlomiej Zolnierkiewicz, Mauro Carvalho Chehab

On Wed, 2008-03-12 at 18:20 +0100, Michael Buesch wrote:
> On Wednesday 12 March 2008 17:54:26 Harvey Harrison wrote:
> > On Wed, 2008-03-12 at 16:13 +0100, Michael Buesch wrote:
> > > So why not call it clamp_const()?
> > > One could even use __builtin_constant_p() and make clamp() use
> > > either clamp_const() or clamp_nonconst() from above automagically.
> > > I'd prefer that.
> > 
> > Did you mean something like this?  No more clamp_val, just clamp and
> > clamp_t.  clamp_t forces all the types, clamp looks at the min and max
> > args, and if they are constants, uses the type of val instead.  If not
> > a constant, the strict typechecking is done.
> 
> > +#define clamp(val, min, max) ({				\
> > +	typeof(val) __val = (val);			\
> > +							\
> > +	if (__builtin_constant_p(min)) {		\
> > +		typeof(val) __min = (min);		\
> > +		__val = __val < __min ? __min: __val;	\
> > +	} else {					\
> > +		typeof(min) __min = (min);		\
> > +		(void) (&__val == &__min);		\
> > +		__val = __val < __min ? __min: __val;	\
> > +	}						\
> > +							\
> > +	if (__builtin_constant_p(max)) {		\
> > +		typeof(val) __max = (max);		\
> > +		__val > __max ? __max: __val;		\
> > +	} else {					\
> > +		typeof(max) __max = (max);		\
> > +		(void) (&__val == &__max);		\
> > +		__val > __max ? __max: __val;		\
> > +	} })
> 
> Yeah, something like that.
> Does returning of the value work over an indentation level, too?
> I dunno this detail of the language.
> But I'd prefer the following for readability anyway:
> 
> +       if (__builtin_constant_p(max)) {                \
> +               typeof(val) __max = (max);              \
> +               __val = __val > __max ? __max: __val;           \
> +       } else {                                        \
> +               typeof(max) __max = (max);              \
> +               (void) (&__val == &__max);              \
> +               __val = __val > __max ? __max: __val;           \
> +       }
> +	__val; })

Yeah, that is better. (and even works).

Harvey


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-03-12 17:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-11 21:11 [PATCH 1/6] kernel: add clamp(), clamp_t() and clamp_val() macros Harvey Harrison
2008-03-12  5:08 ` Andrew Morton
2008-03-12 15:13 ` Michael Buesch
2008-03-12 16:54   ` Harvey Harrison
2008-03-12 17:20     ` Michael Buesch
2008-03-12 17:34       ` Harvey Harrison

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).