Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/libc/copysignl.src
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
_copysignl:
ld hl, 19 ; upper 8 bits of y
add hl, sp
rl (hl) ; extract the signbit of y
ld a, (hl) ; extract the signbit of y
rlca
pop iy, hl, de, bc
push bc, de, hl
rl b ; clear the signbit of x, signbit of y is in the LSB
Expand Down
30 changes: 11 additions & 19 deletions src/libc/ilogbf.src
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,40 @@ _ilogbf:
dec hl
dec hl
dec hl
ld de, (hl)
sbc hl, hl
ex de, hl
; DE is zero
ld hl, (hl)
add hl, hl

adc a, a
jr z, .maybe_subnormal
inc a
scf
jr z, .inf_nan
rr e ; E = 128 or float32_bias + 1
sub a, 128 ; float32_bias + 1
sbc hl, hl
ld l, a
sbc hl, de
ret

.maybe_subnormal:
; DE is zero, Carry unknown
add hl, de
or a, a
sbc hl, de
jr z, .ret_zero
call __ictlz
ex de, hl
; DE was zero, so HL is now zero
dec hl
cpl
add a, 130
sbc hl, hl
ld l, a
ret

.ret_zero:
.inf_nan:
ld hl, $800000 ; FP_ILOGB0
sbc hl, de ; FP_ILOGBNAN or INT_MAX when carry is set
ex de, hl
; DE was zero, so HL is now zero
ld l, 4 ; EDOM
scf
.ret_zero:
ld hl, 4 ; EDOM
ld (_errno), hl
ld hl, ___fe_cur_env
set 4, (hl) ; FE_INVALID
ex de, hl
ld hl, $800000 ; FP_ILOGB0
ret nc
; FP_ILOGBNAN or INT_MAX when carry is set
dec hl
ret

extern _errno
Expand Down
68 changes: 68 additions & 0 deletions src/libc/logbf.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
assume adl=1

section .text

public _logbf, _logb

; float logbf(float)
_logb:
_logbf:
ld hl, 6
ld bc, -3
add hl, sp
ld a, (hl)
add hl, bc
ld c, b ; ld bc, -1
ld hl, (hl)
add hl, hl
adc a, a
jr z, .maybe_subnormal
inc a
jr z, .inf_nan
sub a, 128 ; float32_bias + 1
jr c, .negative_exponent
inc bc ; ld bc, 0
.negative_exponent:
.int_to_float:
; exponent is [-149, 127]
ld c, a
ld a, b ; sign extend
call __ltof
push bc
pop hl
ld e, a
ret

.inf_nan:
; return fabsf(x)
pop bc
ex (sp), hl
push bc
ld e, $7F
ret

.ret_zero:
; HL is zero here
ld l, 4 ; EDOM
ld (_errno), hl
; FE_DIVBYZERO
ld hl, ___fe_cur_env
set 6, (hl)
; -HUGE_VALF
ld hl, $800000
ld e, b ; ld e, $FF
ret

.maybe_subnormal:
add hl, bc
inc hl ; restore HL
jr nc, .ret_zero
call __ictlz
cpl
add a, 130
jr .int_to_float

extern __ltof
extern __ictlz
extern ___fe_cur_env
extern _errno
16 changes: 2 additions & 14 deletions src/libc/logb.c → src/libc/logbl.c
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
#include <errno.h>
#include <fenv.h>
#include <math.h>

float logbf(float x) {
if (isfinite(x)) {
if (iszero(x)) {
feraiseexcept(FE_DIVBYZERO);
return -HUGE_VALF;
}
return (float)ilogbf(x);
}
// infinity and NaN
return fabsf(x);
}

double logb(double) __attribute__((alias("logbf")));

long double logbl(long double x) {
if (isfinite(x)) {
if (iszero(x)) {
errno = EDOM;
feraiseexcept(FE_DIVBYZERO);
return -HUGE_VALL;
}
Expand Down
51 changes: 48 additions & 3 deletions test/floating_point/float32_ilogb/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <fenv.h>
#include <assert.h>
#include <ti/screen.h>
#include <ti/getcsc.h>
Expand All @@ -13,6 +16,25 @@

#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))

#if 0
#define test_printf printf
#else
#define test_printf(...)
#endif

float truth_logbf(float x) {
if (isfinite(x)) {
if (iszero(x)) {
errno = EDOM;
feraiseexcept(FE_DIVBYZERO);
return -HUGE_VALF;
}
return (float)ilogbf(x);
}
// infinity and NaN
return fabsf(x);
}

size_t run_test(void) {
typedef float input_t;
typedef int output_t;
Expand All @@ -24,9 +46,32 @@ size_t run_test(void) {
for (size_t i = 0; i < length; i++) {
int result = ilogbf(input[i]);
if (result != output[i]) {
#if 0
printf("%3zu: %08lX\n\t%d != %d\n", i, input[i], result, output[i]);
#endif
test_printf("%3zu: %08lX\n%d != %d\n", i, input[i], result, output[i]);
return i;
}

errno = 0;
feclearexcept(FE_ALL_EXCEPT);
float f_truth = truth_logbf(input[i]);
unsigned char fe_truth = __fe_cur_env;
int errno_truth = errno;

errno = 0;
feclearexcept(FE_ALL_EXCEPT);
float f_guess = logbf(input[i]);
unsigned char fe_guess = __fe_cur_env;
int errno_guess = errno;

if (memcmp(&f_guess, &f_truth, sizeof(float)) != 0) {
test_printf("%3zu: %08lX %d\n%08lX != %08lX\n", i, input[i], output[i], f_guess, f_truth);
return i;
}
if (fe_guess != fe_truth) {
fputs("fenv fail\n", stdout);
return i;
}
if (errno_guess != errno_truth) {
fputs("errno fail\n", stdout);
return i;
}
}
Expand Down
51 changes: 48 additions & 3 deletions test/floating_point/float64_ilogb/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <fenv.h>
#include <assert.h>
#include <ti/screen.h>
#include <ti/getcsc.h>
Expand All @@ -13,6 +16,25 @@

#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))

#if 0
#define test_printf printf
#else
#define test_printf(...)
#endif

long double truth_logbl(long double x) {
if (isfinite(x)) {
if (iszero(x)) {
errno = EDOM;
feraiseexcept(FE_DIVBYZERO);
return -HUGE_VALL;
}
return (long double)ilogbl(x);
}
// infinity and NaN
return fabsl(x);
}

size_t run_test(void) {
typedef long double input_t;
typedef int output_t;
Expand All @@ -24,9 +46,32 @@ size_t run_test(void) {
for (size_t i = 0; i < length; i++) {
int result = ilogbl(input[i]);
if (result != output[i]) {
#if 0
printf("%4zu: %016llX\n %d != %d\n", i, input[i], result, output[i]);
#endif
test_printf("%4zu: %016llX\n%d != %d\n", i, input[i], result, output[i]);
return i;
}

errno = 0;
feclearexcept(FE_ALL_EXCEPT);
long double f_truth = truth_logbl(input[i]);
unsigned char fe_truth = __fe_cur_env;
int errno_truth = errno;

errno = 0;
feclearexcept(FE_ALL_EXCEPT);
long double f_guess = logbl(input[i]);
unsigned char fe_guess = __fe_cur_env;
int errno_guess = errno;

if (memcmp(&f_guess, &f_truth, sizeof(long double)) != 0) {
test_printf("%4zu:\n%016llX %d\n%016llX !=\n%016llX\n", i, input[i], output[i], f_guess, f_truth);
return i;
}
if (fe_guess != fe_truth) {
fputs("fenv fail\n", stdout);
return i;
}
if (errno_guess != errno_truth) {
fputs("errno fail\n", stdout);
return i;
}
}
Expand Down
Loading