25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * CDDL HEADER START
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * The contents of this file are subject to the terms of the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Common Development and Distribution License (the "License").
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * You may not use this file except in compliance with the License.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * See the License for the specific language governing permissions
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * and limitations under the License.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * CDDL HEADER END
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Use is subject to license terms.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#pragma weak fmaxf = __fmaxf
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fmax(x,y) returns the larger of x and y. If just one of the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * arguments is NaN, fmax returns the other argument. If both
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * arguments are NaN, fmax returns NaN (ideally, one of the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * argument NaNs).
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * C99 does not require that fmax(-0,+0) = fmax(+0,-0) = +0, but
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ideally fmax should satisfy this.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * C99 makes no mention of exceptions for fmax. I suppose ideally
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * either fmax never raises any exceptions or else it raises the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * invalid operation exception if and only if some argument is a
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * signaling NaN. In the former case, fmax should always return
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * one of its arguments. In the latter, fmax shouldn't return a
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * signaling NaN, although when both arguments are signaling NaNs,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * this ideal is at odds with the stipulation that fmax should
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * always return one of its arguments.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Commutativity of fmax follows from the properties listed above
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * except when both arguments are NaN. In that case, fmax may be
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * declared commutative by fiat because there is no portable way
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * to tell different NaNs apart. Ideally fmax would be truly com-
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * mutative for all arguments.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * On SPARC V8, fmax must involve tests and branches. Ideally,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * an implementation on SPARC V9 should avoid branching, using
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * conditional moves instead where necessary, and be as efficient
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * as possible in its use of other resources.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * It appears to be impossible to attain all of the aforementioned
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ideals simultaneously. The implementation below satisfies the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * following (on SPARC):
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 1. fmax(x,y) returns the larger of x and y if neither x nor y
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * is NaN and the non-NaN argument if just one of x or y is NaN.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * If both x and y are NaN, fmax(x,y) returns x unchanged.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 2. fmax(-0,+0) = fmax(+0,-0) = +0.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 3. If either argument is a signaling NaN, fmax raises the invalid
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * operation exception. Otherwise, it raises no exceptions.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include "libm.h" /* for isgreaterequal macro */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisfloat
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis__fmaxf(float x, float y) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * On SPARC v8plus/v9, this could be implemented as follows
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * (assuming %f0 = x, %f1 = y, return value left in %f0):
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fcmps %fcc0,%f1,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fmovsu %fcc0,%f0,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fcmps %fcc0,%f0,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fmovsul %fcc0,%f1,%f0
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * st %f0,[x]
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * st %f1,[y]
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ld [x],%l0
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ld [y],%l1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * and %l0,%l1,%l2
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * sethi %hi(0x80000000),%l3
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * andn %l3,%l2,%l2
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * andn %l0,%l2,%l0
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * st %l0,[x]
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ld [x],%f0
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * If VIS instructions are available, use this code instead:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fcmps %fcc0,%f1,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fmovsu %fcc0,%f0,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fcmps %fcc0,%f0,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fmovsul %fcc0,%f1,%f0
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fands %f0,%f1,%f2
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fzeros %f3
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fnegs %f3,%f3
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fandnot2s %f3,%f2,%f2
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fandnot2s %f0,%f2,%f0
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * If VIS 3.0 instructions are available, use this:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * flcmps %fcc0,%f0,%f1
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fmovslg %fcc0,%f1,%f0 ! move if %fcc0 is 1 or 2
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis union {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis unsigned i;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis float f;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis } xx, yy;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis unsigned s;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* if y is nan, replace it by x */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (y != y)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis y = x;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* if x is nan, replace it by y */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (x != x)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis x = y;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* At this point, x and y are either both numeric, or both NaN */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (!isnan(x) && !isgreaterequal(x, y))
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis x = y;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * clear the sign of the result if either x or y has its sign clear
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis xx.f = x;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis yy.f = y;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis s = ~(xx.i & yy.i) & 0x80000000;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis xx.i &= ~s;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (xx.f);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}