Skip to content

Commit f7305a7

Browse files
jpellegrinikou
andauthored
Add expt (#26)
It signals an error when the exponent is negative, since sigscheme only implements integer math. This is an iterative implementation of exponentiation by squaring - and it works with negative bases. --------- Co-authored-by: Sutou Kouhei <kou@cozmixng.org>
1 parent 0c1120b commit f7305a7

File tree

4 files changed

+37
-1
lines changed

4 files changed

+37
-1
lines changed

doc/spec.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,6 @@ Numbers
439439
- *procedure:* atan z
440440
- *procedure:* atan y x
441441
- *procedure:* sqrt z
442-
- *procedure:* expt z1 z2
443442
- *procedure:* make-rectangular x1 x2
444443
- *procedure:* make-polar x3 x4
445444
- *procedure:* real-part z

src/number.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
=======================================*/
4646
#define ERRMSG_DIV_BY_ZERO "division by zero"
4747
#define ERRMSG_REQ_1_ARG "at least 1 argument required"
48+
#define ERRMSG_NEGATIVE_EXP "negative exponent"
4849

4950
/*=======================================
5051
File Local Type Definitions
@@ -417,3 +418,30 @@ scm_p_remainder(ScmObj _n1, ScmObj _n2)
417418

418419
return MAKE_INT(n1 % n2);
419420
}
421+
422+
SCM_EXPORT ScmObj
423+
scm_p_expt(ScmObj _base, ScmObj _expo)
424+
{
425+
scm_int_t base, expo, result;
426+
DECLARE_FUNCTION("expt", procedure_fixed_2);
427+
428+
ENSURE_INT(_base);
429+
ENSURE_INT(_expo);
430+
431+
base = SCM_INT_VALUE(_base);
432+
expo = SCM_INT_VALUE(_expo);
433+
434+
/* SigScheme only implements integer numbers, so negative
435+
exponents are not allowed. */
436+
if (expo < 0) ERR(ERRMSG_NEGATIVE_EXP);
437+
438+
result = 1;
439+
while (expo > 0) {
440+
if (expo % 2 == 1)
441+
result *= base;
442+
base *= base;
443+
expo /= 2;
444+
}
445+
446+
return MAKE_INT(result);
447+
}

src/sigscheme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,7 @@ SCM_EXPORT ScmObj scm_p_abs(ScmObj _n);
14741474
SCM_EXPORT ScmObj scm_p_quotient(ScmObj _n1, ScmObj _n2);
14751475
SCM_EXPORT ScmObj scm_p_modulo(ScmObj _n1, ScmObj _n2);
14761476
SCM_EXPORT ScmObj scm_p_remainder(ScmObj _n1, ScmObj _n2);
1477+
SCM_EXPORT ScmObj scm_p_expt(ScmObj _n1, ScmObj _n2);
14771478
#endif /* SCM_USE_NUMBER */
14781479

14791480
/* number-io.c */

test/test-number-arith.scm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,5 +1843,13 @@
18431843
-9223372036854775808))"))
18441844
(else
18451845
(assert-fail (tn) "unknown int bitwidth")))
1846+
(tn "expt")
1847+
(assert-equal? (tn) 9 (expt 3 2))
1848+
(assert-equal? (tn) 9 (expt -3 2))
1849+
(assert-equal? (tn) 27 (expt 3 3))
1850+
(assert-equal? (tn) -27 (expt -3 3))
1851+
(assert-equal? (tn) 1 (expt -3 0))
1852+
(assert-equal? (tn) 0 (expt 0 11))
1853+
(assert-error (tn) (lambda () (expt 3 -2)))
18461854

18471855
(total-report)

0 commit comments

Comments
 (0)