diff options
| author | Brian Paul <brianp@vmware.com> | 2010-07-06 11:33:56 -0600 | 
|---|---|---|
| committer | Brian Paul <brianp@vmware.com> | 2010-07-06 11:36:37 -0600 | 
| commit | e834c48100d9e373cb474b6dffa739769ac9ce42 (patch) | |
| tree | 937853ca342e0bfa125905f66ac4747d3de13cf8 /src | |
| parent | 99c8d9b6dac55263b3f0ddce939173ec9a16cf80 (diff) | |
gallivm: finish implementation of lp_build_iceil()
Plus fix minor error in lp_build_iceil() by tweaking the offset value.
And add a bunch of comments for the round(), trunc(), floor(), ceil()
functions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_arit.c | 86 | 
1 files changed, 67 insertions, 19 deletions
| diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index d926b2de18..3ceff86da5 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -847,6 +847,11 @@ lp_build_round_sse41(struct lp_build_context *bld,  } +/** + * Return the integer part of a float (vector) value.  The returned value is + * a float (vector). + * Ex: trunc(-1.5) = 1.0 + */  LLVMValueRef  lp_build_trunc(struct lp_build_context *bld,                 LLVMValueRef a) @@ -869,6 +874,12 @@ lp_build_trunc(struct lp_build_context *bld,  } +/** + * Return float (vector) rounded to nearest integer (vector).  The returned + * value is a float (vector). + * Ex: round(0.9) = 1.0 + * Ex: round(-1.5) = -2.0 + */  LLVMValueRef  lp_build_round(struct lp_build_context *bld,                 LLVMValueRef a) @@ -890,6 +901,11 @@ lp_build_round(struct lp_build_context *bld,  } +/** + * Return floor of float (vector), result is a float (vector) + * Ex: floor(1.1) = 1.0 + * Ex: floor(-1.1) = -2.0 + */  LLVMValueRef  lp_build_floor(struct lp_build_context *bld,                 LLVMValueRef a) @@ -911,6 +927,11 @@ lp_build_floor(struct lp_build_context *bld,  } +/** + * Return ceiling of float (vector), returning float (vector). + * Ex: ceil( 1.1) = 2.0 + * Ex: ceil(-1.1) = -1.0 + */  LLVMValueRef  lp_build_ceil(struct lp_build_context *bld,                LLVMValueRef a) @@ -933,7 +954,7 @@ lp_build_ceil(struct lp_build_context *bld,  /** - * Return fractional part of 'a' computed as a - floor(f) + * Return fractional part of 'a' computed as a - floor(a)   * Typically used in texture coord arithmetic.   */  LLVMValueRef @@ -946,8 +967,9 @@ lp_build_fract(struct lp_build_context *bld,  /** - * Convert to integer, through whichever rounding method that's fastest, - * typically truncating toward zero. + * Return the integer part of a float (vector) value.  The returned value is + * an integer (vector). + * Ex: itrunc(-1.5) = 1   */  LLVMValueRef  lp_build_itrunc(struct lp_build_context *bld, @@ -964,7 +986,10 @@ lp_build_itrunc(struct lp_build_context *bld,  /** - * Convert float[] to int[] with round(). + * Return float (vector) rounded to nearest integer (vector).  The returned + * value is an integer (vector). + * Ex: iround(0.9) = 1 + * Ex: iround(-1.5) = -2   */  LLVMValueRef  lp_build_iround(struct lp_build_context *bld, @@ -1007,7 +1032,9 @@ lp_build_iround(struct lp_build_context *bld,  /** - * Convert float[] to int[] with floor(). + * Return floor of float (vector), result is an int (vector) + * Ex: ifloor(1.1) = 1.0 + * Ex: ifloor(-1.1) = -2.0   */  LLVMValueRef  lp_build_ifloor(struct lp_build_context *bld, @@ -1034,29 +1061,31 @@ lp_build_ifloor(struct lp_build_context *bld,        /* sign = a < 0 ? ~0 : 0 */        sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");        sign = LLVMBuildAnd(bld->builder, sign, mask, ""); -      sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), ""); -      lp_build_name(sign, "floor.sign"); +      sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), "ifloor.sign");        /* offset = -0.99999(9)f */ -      offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa)); +      offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 10)/((unsigned long long)1 << mantissa));        offset = LLVMConstBitCast(offset, int_vec_type); -      /* offset = a < 0 ? -0.99999(9)f : 0.0f */ +      /* offset = a < 0 ? offset : 0.0f */        offset = LLVMBuildAnd(bld->builder, offset, sign, ""); -      offset = LLVMBuildBitCast(bld->builder, offset, vec_type, ""); -      lp_build_name(offset, "floor.offset"); +      offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "ifloor.offset"); -      res = LLVMBuildAdd(bld->builder, a, offset, ""); -      lp_build_name(res, "floor.res"); +      res = LLVMBuildAdd(bld->builder, a, offset, "ifloor.res");     } -   res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, ""); -   lp_build_name(res, "floor"); +   /* round to nearest (toward zero) */ +   res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "ifloor.res");     return res;  } +/** + * Return ceiling of float (vector), returning int (vector). + * Ex: iceil( 1.1) = 2 + * Ex: iceil(-1.1) = -1 + */  LLVMValueRef  lp_build_iceil(struct lp_build_context *bld,                 LLVMValueRef a) @@ -1072,12 +1101,31 @@ lp_build_iceil(struct lp_build_context *bld,        res = lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_CEIL);     }     else { -      /* TODO: mimic lp_build_ifloor() here */ -      assert(0); -      res = bld->undef; +      LLVMTypeRef vec_type = lp_build_vec_type(type); +      unsigned mantissa = lp_mantissa(type); +      LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); +      LLVMValueRef sign; +      LLVMValueRef offset; + +      /* sign = a < 0 ? 0 : ~0 */ +      sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); +      sign = LLVMBuildAnd(bld->builder, sign, mask, ""); +      sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), "iceil.sign"); +      sign = LLVMBuildNot(bld->builder, sign, "iceil.not"); + +      /* offset = 0.99999(9)f */ +      offset = lp_build_const_vec(type, (double)(((unsigned long long)1 << mantissa) - 10)/((unsigned long long)1 << mantissa)); +      offset = LLVMConstBitCast(offset, int_vec_type); + +      /* offset = a < 0 ? 0.0 : offset */ +      offset = LLVMBuildAnd(bld->builder, offset, sign, ""); +      offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "iceil.offset"); + +      res = LLVMBuildAdd(bld->builder, a, offset, "iceil.res");     } -   res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, ""); +   /* round to nearest (toward zero) */ +   res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "iceil.res");     return res;  } | 
