I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Ethiopian multiplication

(Redirected from Ethiopian Multiplication)
Ethiopian multiplication
You are encouraged to solve this task according to the task description, using any language you may know.

Ethiopian multiplication is a method of multiplying integers using only addition, doubling, and halving.

Method:

1. Take two numbers to be multiplied and write them down at the top of two columns.
2. In the left-hand column repeatedly halve the last number, discarding any remainders, and write the result below the last in the same column, until you write a value of 1.
3. In the right-hand column repeatedly double the last number and write the result below. stop when you add a result in the same row as where the left hand column shows 1.
4. Examine the table produced and discard any row where the value in the left column is even.
5. Sum the values in the right-hand column that remain to produce the result of multiplying the original two numbers together

For example:   17 × 34

       17    34


Halving the first column:

       17    34
8
4
2
1


Doubling the second column:

       17    34
8    68
4   136
2   272
1   544


Strike-out rows whose first cell is even:

       17    34
8    68
4   136
2   272
1   544


Sum the remaining numbers in the right-hand column:

       17    34
8    --
4   ---
2   ---
1   544
====
578


So 17 multiplied by 34, by the Ethiopian method is 578.

The task is to define three named functions/methods/procedures/subroutines:

1. one to halve an integer,
2. one to double an integer, and
3. one to state if an integer is even.

Use these functions to create a function that does Ethiopian multiplication.

References

## 11l

Translation of: Python
F halve(x)   R x I/ 2 F double(x)   R x * 2 F even(x)   R !(x % 2) F ethiopian(=multiplier, =multiplicand)   V result = 0    L multiplier >= 1      I !even(multiplier)         result += multiplicand      multiplier = halve(multiplier)      multiplicand = double(multiplicand)    R result print(ethiopian(17, 34))
Output:
578

## 8080 Assembly

The 8080 does not have a hardware multiplier, but it does have addition and rotation, so this code is actually useful. Indeed, it is pretty much the standard algorithm for general multiplication on processors that do not have a hardware multiplier.

You would not normally name the sections (halve, double, even), since they rely on each other and cannot be called independently. Pulling them out entirely would entail a performance hit and make the whole thing much less elegant, so I've done it this way as a sort of compromise.

	org	100h	jmp	demo	;;;	HL = BC * DE	;;;	BC is left column, DE is right columnemul:	lxi	h,0	; HL will be the accumulator ztest:	mov	a,b	; Check if the left column is zero.	ora	c	; If so, stop.	rz  halve:	mov	a,b	; Halve BC by rotating it right.	rar		; We know the carry is zero here because of the ORA.	mov	b,a	; So rotate the top half first,	mov	a,c	; Then the bottom half	rar		; This leaves the old low bit in the carry flag,	mov	c,a	; so this also lets us do the even/odd test in one go. even:	jnc	$+4 ; If no carry, the number is even, so skip (strikethrough) dad d ; But if odd, add the number in the right column double: xchg ; Doubling DE is a bit easier since you can add dad h ; HL to itself in one go, and XCHG swaps DE and HL xchg jmp ztest ; We want to do the whole thing again until BC is zero ;;; Demo code, print 17 * 34demo: lxi b,17 ; Load 17 into BC (left column) lxi d,34 ; Load 34 into DE (right column) call emul ; Do the multiplication print: lxi b,-10 ; Decimal output routine (not very interesting here, lxi d,pbuf ; but without it you can't see the result) push ddigit: lxi d,-1dloop: inx d dad b jc dloop mvi a,58 add l pop h dcx h mov m,a push h xchg mov a,h ora l jnz digit pop d mvi c,9 jmp 5 db '*****'pbuf: db '$'
Output:
578

## ACL2

(include-book "arithmetic-3/top" :dir :system) (defun halve (x)   (floor x 2)) (defun double (x)   (* x 2)) (defun is-even (x)   (evenp x)) (defun multiply (x y)   (if (zp (1- x))       y       (+ (if (is-even x)              0              y)          (multiply (halve x) (double y)))))

## Action!

INT FUNC EthopianMult(INT a,b)  INT res   PrintF("Ethopian multiplication %I by %I:%E",a,b)  res=0  WHILE a>=1  DO    IF a MOD 2=0 THEN      PrintF("%I %I strike%E",a,b)    ELSE      PrintF("%I %I keep%E",a,b)      res==+b    FI    a==/2    b==*2  ODRETURN (res) PROC Main()  INT res   res=EthopianMult(17,34)  PrintF("Result is %I",res)RETURN
Output:
Ethopian multiplication 17 by 34:
17 34 keep
8 68 strike
4 136 strike
2 272 strike
1 544 keep
Result is 578


## ActionScript

Works with: ActionScript version 2.0
function Divide(a:Number):Number {	return ((a-(a%2))/2);}function Multiply(a:Number):Number {	return (a *= 2);}function isEven(a:Number):Boolean {	if (a%2 == 0) {		return (true);	} else {		return (false);	}}function Ethiopian(left:Number, right:Number) {	var r:Number = 0;	trace(left+"     "+right);	while (left != 1) {		var State:String = "Keep";		if (isEven(Divide(left))) {			State = "Strike";		}		trace(Divide(left)+"     "+Multiply(right)+"  "+State);		left = Divide(left);		right = Multiply(right);		if (State == "Keep") {			r += right;		}	}	trace("="+"      "+r);}}
Output:

ex. Ethiopian(17,34);

17     34
8     68  Strike
4     136  Strike
2     272  Strike
1     544  Keep


 with ada.text_io;use ada.text_io; procedure ethiopian is  function double  (n : Natural) return Natural is (2*n);  function halve   (n : Natural) return Natural is (n/2);  function is_even (n : Natural) return Boolean is (n mod 2 = 0);   function mul (l, r : Natural) return Natural is   (if l = 0 then 0 elsif l = 1 then r elsif is_even (l) then mul (halve (l),double (r))    else r + double (mul (halve (l), r))); begin  put_line (mul (17,34)'img);end ethiopian;

## Aime

Translation of: C
voidhalve(integer &x){    x >>= 1;} voiddouble(integer &x){    x <<= 1;} integeriseven(integer x){    return (x & 1) == 0;} integerethiopian(integer plier, integer plicand, integer tutor){    integer result;     result = 0;     if (tutor) {        o_form("ethiopian multiplication of ~ by ~\n", plier, plicand);    }     while (plier >= 1) {        if (iseven(plier)) {            if (tutor) {                o_form("/w4/ /w6/ struck\n", plier, plicand);            }        } else {            if (tutor) {                o_form("/w4/ /w6/ kept\n", plier, plicand);            }             result += plicand;        }         halve(plier);        double(plicand);    }     return result;} integermain(void){    o_integer(ethiopian(17, 34, 1));    o_byte('\n');     return 0;}
 17     34 kept
8     68 struck
4    136 struck
2    272 struck
1    544 kept
578


## ALGOL 68

Translation of: C
Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
PROC halve = (REF INT x)VOID: x := ABS(BIN x SHR 1);PROC doublit = (REF INT x)VOID: x := ABS(BIN x SHL 1);PROC iseven = (#CONST# INT x)BOOL: NOT ODD x; PROC ethiopian = (INT in plier,              INT in plicand, #CONST# BOOL tutor)INT:(  INT plier := in plier, plicand := in plicand;  INT result:=0;   IF tutor THEN    printf(($"ethiopian multiplication of "g(0)," by "g(0)l$, plier, plicand)) FI;   WHILE plier >= 1 DO    IF iseven(plier) THEN      IF tutor THEN printf(($" "4d," "6d" struck"l$, plier, plicand)) FI    ELSE      IF tutor THEN printf(($" "4d," "6d" kept"l$, plier, plicand)) FI;      result +:= plicand    FI;    halve(plier); doublit(plicand)  OD;  result); main:(  printf(($g(0)l$, ethiopian(17, 34, TRUE))))
Output:
ethiopian multiplication of 17 by 34
0017  000034 kept
0008  000068 struck
0004  000136 struck
0002  000272 struck
0001  000544 kept
578


## ALGOL-M

 BEGIN INTEGER FUNCTION HALF(I);INTEGER I;BEGIN  HALF := I / 2;END; INTEGER FUNCTION DOUBLE(I);INTEGER I;BEGIN  DOUBLE := I + I;END; % RETURN 1 IF EVEN, OTHERWISE 0 %INTEGER FUNCTION EVEN(I);INTEGER I;BEGIN  EVEN := 1 - (I - 2 * (I / 2));END; % RETURN I * J AND OPTIONALLY SHOW COMPUTATIONAL STEPS %INTEGER FUNCTION ETHIOPIAN(I, J, SHOW);INTEGER I, J, SHOW;BEGIN  INTEGER P, YES;  YES := 1;  P := 0;  WHILE I >= 1 DO    BEGIN      IF EVEN(I) = YES THEN        BEGIN          IF SHOW = YES THEN WRITE(I,"  ----", J);        END      ELSE        BEGIN          IF SHOW = YES THEN WRITE(I,J);          P := P + J;        END;      I := HALF(I);      J := DOUBLE(J);    END;  IF SHOW = YES THEN WRITE("     =");  ETHIOPIAN := P;END; % EXERCISE THE FUNCTION %INTEGER YES;YES := 1;WRITE(ETHIOPIAN(17,34,YES)); END
Output:
    17   34
8 ----   68
4 ----  136
2 ----  272
1  544
=  578


## ALGOL W

begin    % returns half of a %    integer procedure halve  ( integer value a ) ; a div 2;    % returns a doubled %    integer procedure double ( integer value a ) ; a * 2;    % returns true if a is even, false otherwise %    logical procedure even   ( integer value a ) ; not odd( a );    % returns the product of a and b using ethopian multiplication %    % rather than keep a table of the intermediate results,        %    % we examine then as they are generated                        %    integer procedure ethopianMultiplication ( integer value a, b ) ;    begin        integer v, r, accumulator;        v           := a;        r           := b;        accumulator := 0;        i_w := 4; s_w := 0; % set output formatting %        while begin            write( v );            if even( v ) then writeon( "    ---" )            else begin                accumulator := accumulator + r;                writeon( "   ", r );            end;            v := halve( v );            r := double( r );            v > 0        end do begin end;        write( "      =====" );        accumulator    end ethopianMultiplication ;    % task test case %    begin        integer m;        m := ethopianMultiplication( 17, 34 );        write( "       ", m )    endend.
Output:
  17     34
8    ---
4    ---
2    ---
1    544
=====
578


## AppleScript

Translation of: JavaScript

Note that this algorithm, already described in the Rhind Papyrus (c. BCE 1650), can be used to multiply strings as well as integers, if we change the identity element from 0 to the empty string, and replace integer addition with string concatenation.

on run    {ethMult(17, 34), ethMult("Rhind", 9)}     --> {578, "RhindRhindRhindRhindRhindRhindRhindRhind"}end run  -- Int -> Int -> Int-- or-- Int -> String -> Stringon ethMult(m, n)    script fns        property identity : missing value        property plus : missing value         on half(n) -- 1. half an integer (div 2)            n div 2        end half         on double(n) -- 2. double (add to self)            plus(n, n)        end double         on isEven(n) -- 3. is n even ? (mod 2 > 0)            (n mod 2) > 0        end isEven         on chooseFns(c)            if c is string then                set identity of fns to ""                set plus of fns to plusString of fns            else                set identity of fns to 0                set plus of fns to plusInteger of fns            end if        end chooseFns         on plusInteger(a, b)            a + b        end plusInteger         on plusString(a, b)            a & b        end plusString    end script     chooseFns(class of m) of fns      -- MAIN PROCESS OF CALCULATION     set o to identity of fns    if n < 1 then return o     repeat while (n > 1)        if isEven(n) of fns then -- 3. is n even ? (mod 2 > 0)            set o to plus(o, m) of fns        end if        set n to half(n) of fns -- 1. half an integer (div 2)        set m to double(m) of fns -- 2. double  (add to self)    end repeat    return plus(o, m) of fnsend ethMult
Output:
{578, "RhindRhindRhindRhindRhindRhindRhindRhindRhind"}

## Arturo

halve: function [x]-> shr x 1double: function [x]-> shl x 1 ; even? already exists ethiopian: function [x y][    prod: 0    while [x > 0][        unless even? x [prod: prod + y]        x: halve x        y: double y    ]    return prod] print ethiopian 17 34print ethiopian 2 3
Output:
578
6

## AutoHotkey

MsgBox % Ethiopian(17, 34) "n" Ethiopian2(17, 34) ; func definitions:half( x ) {	return x >> 1} double( x ) {	return x << 1} isEven( x ) {	return x & 1 == 0} Ethiopian( a, b ) {	r := 0	While (a >= 1) {		if !isEven(a)			r += b		a := half(a)		b := double(b)	}	return r} ; or a recursive function:Ethiopian2( a, b, r = 0 ) { ;omit r param on initial call	return a==1 ? r+b : Ethiopian2( half(a), double(b), !isEven(a) ? r+b : r )}

## AutoIt

 Func Halve($x) Return Int($x/2)EndFunc Func Double($x) Return ($x*2)EndFunc Func IsEven($x) Return (Mod($x,2) == 0)EndFunc ; this version also supports negative parametersFunc Ethiopian($nPlier,$nPlicand, $bTutor = True) Local$nResult = 0	If ($nPlier < 0) Then$nPlier =- $nPlier$nPlicand =- $nPlicand ElseIf ($nPlicand > 0) And ($nPlier >$nPlicand) Then		$nPlier =$nPlicand		$nPlicand =$nPlier	EndIf	If $bTutor Then _ ConsoleWrite(StringFormat("Ethiopian multiplication of %d by %d...\n",$nPlier, $nPlicand)) While ($nPlier >= 1)		If Not IsEven($nPlier) Then$nResult += $nPlicand If$bTutor Then ConsoleWrite(StringFormat("%d\t%d\tKeep\n", $nPlier,$nPlicand))		Else			If $bTutor Then ConsoleWrite(StringFormat("%d\t%d\tStrike\n",$nPlier, $nPlicand)) EndIf$nPlier = Halve($nPlier)$nPlicand = Double($nPlicand) WEnd If$bTutor Then ConsoleWrite(StringFormat("Answer = %d\n", $nResult)) Return$nResultEndFunc MsgBox(0, "Ethiopian multiplication of 17 by 34", Ethiopian(17, 34) ) 

## AWK

Implemented without the tutor.

function halve(x){  return int(x/2)} function double(x){  return x*2} function iseven(x){  return x%2 == 0} function ethiopian(plier, plicand){  r = 0  while(plier >= 1) {    if ( !iseven(plier) ) {      r += plicand    }    plier = halve(plier)    plicand = double(plicand)  }  return r} BEGIN {  print ethiopian(17, 34)}

## BASIC

### ASIC

 REM Ethiopian multiplicationX = 17Y = 34TOT = 0WHILE X >= 1  PRINT X;  PRINT " ";  A = X  GOSUB CHECKEVEN:  IF ISEVEN = 0 THEN    TOT = TOT + Y    PRINT Y;  ENDIF  PRINT  A = X  GOSUB HALVE:   X = A  A = Y  GOSUB DOUBLE:   Y = AWENDPRINT "=      ";PRINT TOTEND REM Subroutines are required, thoughREM they complicate the code DOUBLE:A = 2 * ARETURN HALVE:A = A / 2RETURN CHECKEVEN: REM ISEVEN - result (0 if A odd, 1 otherwise)ISEVEN = A MOD 2ISEVEN = 1 - ISEVENRETURN 
Output:
    17     34
8
4
2
1    544
=         578


### BASIC

Works with QBasic. While building the table, it's easier to simply not print unused values, rather than have to go back and strike them out afterward. (Both that and the actual adding happen in the "IF NOT (isEven(x))" block.)

DECLARE FUNCTION half% (a AS INTEGER)DECLARE FUNCTION doub% (a AS INTEGER)DECLARE FUNCTION isEven% (a AS INTEGER) DIM x AS INTEGER, y AS INTEGER, outP AS INTEGER x = 17y = 34 DO    PRINT x,    IF NOT (isEven(x)) THEN        outP = outP + y        PRINT y    ELSE        PRINT    END IF    IF x < 2 THEN EXIT DO    x = half(x)    y = doub(y)LOOP PRINT " =", outP FUNCTION doub% (a AS INTEGER)    doub% = a * 2END FUNCTION FUNCTION half% (a AS INTEGER)    half% = a \ 2END FUNCTION FUNCTION isEven% (a AS INTEGER)    isEven% = (a MOD 2) - 1END FUNCTION
Output:
17            34
8
4
2
1             544
=             578


### BBC BASIC

      x% = 17      y% = 34       REPEAT        IF NOT FNeven(x%) THEN          p% += y%          PRINT x%, y%        ELSE          PRINT x%, "       ---"        ENDIF        x% = FNhalve(x%)        y% = FNdouble(y%)      UNTIL x% = 0      PRINT " " , "       ==="      PRINT " " , p%      END       DEF FNdouble(A%) = A% * 2       DEF FNhalve(A%) = A% DIV 2       DEF FNeven(A%) = ((A% AND 1) = 0)
Output:
       17        34
8       ---
4       ---
2       ---
1       544
===
578


### FreeBASIC

Function double_(y As String) As String    Var answer="0"+y    Var addcarry=0    For n_ As Integer=Len(y)-1 To 0 Step -1         Var addup=y[n_]+y[n_]-96        answer[n_+1]=(addup+addcarry) Mod 10+48        addcarry=(-(10<=(addup+addcarry)))    Next n_     answer[0]=addcarry+48    Return Ltrim(answer,"0")End Function Function Accumulate(NUM1 As String,NUM2 As String) As String    Var three="0"+NUM1    Var two=String(len(NUM1)-len(NUM2),"0")+NUM2    Var addcarry=0    For n2 As Integer=len(NUM1)-1 To 0 Step -1         Var addup=two[n2]+NUM1[n2]-96        three[n2+1]=(addup+addcarry) Mod 10+48        addcarry=(-(10<=(addup+addcarry)))    Next n2     three[0]=addcarry+48    three=Ltrim(three,"0")    If three="" Then Return "0"    Return three End Function Function Half(Byref x As String) As String    Var carry=0    For z As Integer=0 To Len(x)-1        Var temp=(x[z]-48+carry)        Var main=temp Shr 1        carry=(temp And 1) Shl 3 +(temp And 1) Shl 1        x[z]=main+48    Next z    x= Ltrim(x,"0")    Return xEnd Function Function IsEven(x As String) As Integer    If x[Len(x)-1] And 1  Then Return 0    return -1End Function Function EthiopianMultiply(n1 As String,n2 As String) As String    Dim As String x=n1,y=n2    If Len(y)>Len(x) Then Swap y,x    'set the largest one to be halfed    If Len(y)=Len(x) Then        If x<y Then Swap y,x    End If    Dim As String ans    Dim As String temprint,odd    While x<>""        temprint=""        odd=""        If  not IsEven(x) Then            temprint=" *"            odd=" <-- odd"            ans=Accumulate(y,ans)        End If        Print x;odd;tab(30);y;temprint        x=Half(x)         y= Double_(y)    Wend    Return ansEnd Function'=================  Example ====================PrintDim As String s1="17"Dim As String s2="34"Print "Half";tab(30);"Double     * marks those accumulated"print "Biggest";tab(30);"Smallest"  Print Var ans= EthiopianMultiply(s1,s2) PrintPrintPrint "Final answer"Print " ";ansprint "Float check"Print Val(s1)*Val(s2) Sleep 
note: algorithm uses strings instead of integers
Output:
Half                         Double     * marks those accumulated
Biggest                      Smallest
34                           17
17 <-- odd                   34 *
8                            68
4                            136
2                            272
1 <-- odd                    544 *

578

Float check

578

### GW-BASIC

10 DEF FNE(A)=(A+1) MOD 220 DEF FNH(A)=INT(A/2)30 DEF FND(A)=2*A40 X=17:Y=34:TOT=050 WHILE X>=160 PRINT X,70 IF FNE(X)=0 THEN TOT=TOT+Y:PRINT Y ELSE PRINT80 X=FNH(X):Y=FND(Y)90 WEND100 PRINT "=", TOT

x = 17y = 34msg$= str$(x) + " * " + str$(y) + " = "Print str$(x) + "    " + str$(y)'In this routine we will not worry about discarding the right hand value whos left hand partner is even;'we will just not add it to our product.Do Until x < 2 If Not(isEven(x)) Then product = (product + y) End If x = halveInt(x) y = doubleInt(y) Print str$(x) + "    " + str$(y)Loopproduct = (product + y)If (x < 0) Then product = (product * -1)Print msg$ + str$(product) Function isEven(num) isEven = Abs(Not(num Mod 2))End Function Function halveInt(num) halveInt = Int(num/ 2)End Function Function doubleInt(num) doubleInt = Int(num * 2)End Function ### Microsoft Small Basic  x = 17y = 34tot = 0While x >= 1 TextWindow.Write(x) TextWindow.CursorLeft = 10 If Math.Remainder(x + 1, 2) = 0 Then tot = tot + y TextWindow.WriteLine(y) Else TextWindow.WriteLine("") EndIf x = Math.Floor(x / 2) y = 2 * yEndWhileTextWindow.Write("=")TextWindow.CursorLeft = 10 TextWindow.WriteLine(tot)  ### Nascom BASIC Translation of: Modula-2 Works with: Nascom ROM BASIC version 4.7  10 REM Ethiopian multiplication20 DEF FND(A)=2*A30 DEF FNH(A)=INT(A/2)40 DEF FNE(A)=X-INT(X/2)*2-150 X=1760 Y=3470 TT=080 IF X<1 THEN 15090 NR=X:GOSUB 1000:PRINT " ";100 IF FNE(X)=0 THEN TT=TT+Y:NR=Y:GOSUB 1000110 PRINT120 X=FNH(X)130 Y=FND(Y)140 GOTO 80150 PRINT "= ";160 NR=TT:GOSUB 1000:PRINT170 END 995 REM Print NR in 9 fields1000 S$=STR$(NR)1010 PRINT SPC(9-LEN(S$));S$;1020 RETURN  Output:  17 34 8 4 2 1 544 = 578  ### PureBasic Procedure isEven(x) ProcedureReturn (x & 1) ! 1EndProcedure Procedure halveValue(x) ProcedureReturn x / 2EndProcedure Procedure doubleValue(x) ProcedureReturn x << 1EndProcedure Procedure EthiopianMultiply(x, y) Protected sum Print("Ethiopian multiplication of " + Str(x) + " and " + Str(y) + " ... ") Repeat If Not isEven(x) sum + y EndIf x = halveValue(x) y = doubleValue(y) Until x < 1 PrintN(" equals " + Str(sum)) ProcedureReturn sum EndProcedure If OpenConsole() EthiopianMultiply(17,34) Print(#CRLF$ + #CRLF$+ "Press ENTER to exit") Input() CloseConsole()EndIf Output: Ethiopian multiplication of 17 and 34 ... equals 578  It became apparent that according to the way the Ethiopian method is described above it can't produce a correct result if the first multiplicand (the one being repeatedly halved) is negative. I've addressed that in this variation. If the first multiplicand is negative then the resulting sum (which may already be positive or negative) is negated. Procedure isEven(x) ProcedureReturn (x & 1) ! 1EndProcedure Procedure halveValue(x) ProcedureReturn x / 2 EndProcedure Procedure doubleValue(x) ProcedureReturn x << 1EndProcedure Procedure EthiopianMultiply(x, y) Protected sum, sign = x Print("Ethiopian multiplication of " + Str(x) + " and " + Str(y) + " ...") Repeat If Not isEven(x) sum + y EndIf x = halveValue(x) y = doubleValue(y) Until x = 0 If sign < 0 : sum * -1: EndIf PrintN(" equals " + Str(sum)) ProcedureReturn sum EndProcedure If OpenConsole() EthiopianMultiply(17,34) EthiopianMultiply(-17,34) EthiopianMultiply(-17,-34) Print(#CRLF$ + #CRLF$+ "Press ENTER to exit") Input() CloseConsole()EndIf Output: Ethiopian multiplication of 17 and 34 ... equals 578 Ethiopian multiplication of -17 and 34 ... equals -578 Ethiopian multiplication of -17 and -34 ... equals 578  ### QB64 PRINT multiply(17, 34) SUB twice (n AS LONG) n = n * 2END SUB SUB halve (n AS LONG) n = n / 2END SUB FUNCTION odd%% (n AS LONG) odd%% = (n AND 1) * -1END FUNCTION FUNCTION multiply& (a AS LONG, b AS LONG) DIM AS LONG result, multiplicand, multiplier multiplicand = a multiplier = b WHILE multiplicand <> 0 IF odd(multiplicand) THEN result = result + multiplier halve multiplicand twice multiplier WEND multiply& = resultEND FUNCTION Output: 578  ### Sinclair ZX81 BASIC Requires at least 2k of RAM. The specification is emphatic about wanting named functions: in a language where user-defined functions do not exist, the best we can do is to use subroutines and assign their line numbers to variables. This allows us to GOSUB HALVE instead of having to GOSUB 320. (It would however be more idiomatic to avoid using subroutines at all, for simple operations like these, and to refer to them by line number if they were used.)  10 LET HALVE=320 20 LET DOUBLE=340 30 LET EVEN=360 40 DIM L(20) 50 DIM R(20) 60 INPUT L(1) 70 INPUT R(1) 80 LET I=1 90 PRINT L(1),R(1)100 IF L(I)=1 THEN GOTO 200110 LET I=I+1120 IF I>20 THEN STOP130 LET X=L(I-1)140 GOSUB HALVE150 LET L(I)=Y160 LET X=R(I-1)170 GOSUB DOUBLE180 LET R(I)=Y190 GOTO 90200 FOR K=1 TO I210 LET X=L(K)220 GOSUB EVEN230 IF NOT Y THEN GOTO 260240 LET R(K)=0250 PRINT AT K-1,16;" "260 NEXT K270 LET A=0280 FOR K=1 TO I290 LET A=A+R(K)300 NEXT K310 GOTO 380320 LET Y=INT (X/2)330 RETURN340 LET Y=X*2350 RETURN360 LET Y=X/2=INT (X/2)370 RETURN380 PRINT AT I+1,16;A Input: 17 34 Output: 17 34 8 4 2 1 544 578 ### Tiny BASIC  REM Ethiopian multiplication LET X=17 LET Y=34 LET T=010 IF X<1 THEN GOTO 40 LET A=X GOSUB 400 IF E=0 THEN GOTO 20 LET T=T+Y PRINT X,", ",Y, " (kept)" GOTO 3020 PRINT X,", ",Y30 GOSUB 300 LET X=A LET A=Y GOSUB 200 LET Y=A GOTO 1040 PRINT "------------" PRINT "= ",T," (sum of kept second vals)" END REM Subroutines are required, though REM they complicate the code REM -- Double -- REM A - param.200 LET A=2*A RETURN REM -- Halve -- REM A - param.300 LET A=A/2 RETURN REM -- Is even -- REM A - param.; E - result (0 - false)400 LET E=A-(A/2)*2 RETURN  Output: 17, 34 (kept) 8, 68 4, 136 2, 272 1, 544 (kept) ------------ = 578 (sum of kept second vals)  ### True BASIC A translation of BBC BASIC. True BASIC does not have Boolean operations built-in.  !RosettaCode: Ethiopian Multiplication! True BASIC v6.007PROGRAM EthiopianMultiplication DECLARE DEF FNdouble DECLARE DEF FNhalve DECLARE DEF FNeven LET x = 17 LET y = 34 DO IF FNeven(x) = 0 THEN LET p = p + y PRINT x,y ELSE PRINT x," ---" END IF LET x = FNhalve(x) LET y = FNdouble(y) LOOP UNTIL x = 0 PRINT " ", " ===" PRINT " ", p GET KEY done DEF FNdouble(A) = A * 2 DEF FNhalve(A) = INT(A / 2) DEF FNeven(A) = MOD(A+1,2)END  ### XBasic Translation of: Modula-2 Works with: Windows XBasic  ' Ethiopian multiplicationPROGRAM "ethmult"VERSION "0.0000" DECLARE FUNCTION Entry()INTERNAL FUNCTION Double(@a&&)INTERNAL FUNCTION Halve(@a&&)INTERNAL FUNCTION IsEven(a&&) FUNCTION Entry() x&& = 17 y&& = 34 tot&& = 0 DO WHILE x&& >= 1 PRINT FORMAT$("#########", x&&);    PRINT " ";    IFF IsEven(x&&) THEN      tot&& = tot&& + y&&      PRINT FORMAT$("#########", y&&); END IF PRINT Halve(@x&&) Double(@y&&) LOOP PRINT "= "; PRINT FORMAT$("#########", tot&&);  PRINTEND FUNCTION FUNCTION Double(a&&)  a&& = 2 * a&&END FUNCTION FUNCTION Halve(a&&)  a&& = a&& / 2END FUNCTION FUNCTION IsEven(a&&)  RETURN a&& MOD 2 = 0END FUNCTIONEND PROGRAM 
Output:
       17        34
8
4
2
1       544
=               578


## Batch File

 @echo off:: Pick 2 random, non-zero, 2-digit numbers to send to :_mainset /a param1=%random% %% 98 + 1set /a param2=%random% %% 98 + 1call:_main %param1% %param2%pause>nulexit /b:: This is the main function that outputs the answer in the form of "%1 * %2 = %answer%":_mainsetlocal enabledelayedexpansionset l0=%1set r0=%2set leftcount=1set lefttempcount=0set rightcount=1set righttempcount=0:: Creates an array ("l[]") with the :_halve function. %l0% is the initial left number parsed:: This section will loop until the most recent member of "l[]" is equal to 0:leftset /a lefttempcount=%leftcount%-1if !l%lefttempcount%!==1 goto rightcall:_halve !l%lefttempcount%!set l%leftcount%=%errorlevel%set /a leftcount+=1goto left:: Creates an array ("r[]") with the :_double function, %r0% is the initial right number parsed:: This section will loop until it has the same amount of entries as "l[]":rightset /a righttempcount=%rightcount%-1if %rightcount%==%leftcount% goto bothcall:_double !r%righttempcount%!set r%rightcount%=%errorlevel%set /a rightcount+=1goto right :both:: Creates an boolean array ("e[]") corresponding with whether or not the respective "l[]" entry is evenfor /l %%i in (0,1,%lefttempcount%) do (  call:_even !l%%i!  set e%%i=!errorlevel!):: Adds up all entries of "r[]" based on the value of "e[]", respectivelyset answer=0for /l %%i in (0,1,%lefttempcount%) do (  if !e%%i!==1 (    set /a answer+=!r%%i!  :: Everything from this-----------------------------    set iseven%%i=KEEP  ) else (    set iseven%%i=STRIKE  )  echo L: !l%%i! R: !r%%i! - !iseven%%i!  :: To this, is for cosmetics and is optional-------- )echo %l0% * %r0% = %answer%exit /b:: These are the three functions being used. The output of these functions are expressed in the errorlevel that they return:_halvesetlocalset /a temp=%1/2exit /b %temp% :_doublesetlocalset /a temp=%1*2exit /b %temp% :_evensetlocalset int=%1set /a modint=%int% %% 2exit /b %modint% 
Output:
L: 17 R: 34 - KEEP
L: 8 R: 68 - STRIKE
L: 4 R: 136 - STRIKE
L: 2 R: 272 - STRIKE
L: 1 R: 544 - KEEP
17 * 34 = 578


## BCPL

get "libhdr" let halve(i)  = i>>1and double(i) = i<<1and even(i)   = (i&1) = 0 let emul(x, y)      = emulr(x, y, 0) and emulr(x, y, ac) =    x=0 -> ac,    emulr(halve(x), double(y), even(x) -> ac, ac + y) let start() be writef("%N*N", emul(17, 34))
Output:
578

( (halve=.div$(!arg.2))& (double=.2*!arg)& (isEven=.mod$(!arg.2):0)& ( mul  =   a b as bs newbs result    .   !arg:(?as.?bs)      &   whl        ' ( !as:? (%@:~1:?a)          & !as halve$!a:?as & !bs:? %@?b & !bs double$!b:?bs          )      & :?newbs      &   whl        ' ( !as:%@?a ?as          & !bs:%@?b ?bs          & (isEven$!a|!newbs !b:?newbs) ) & 0:?result & whl ' (!newbs:%@?b ?newbs&!b+!result:?result) & !result )& out$(mul$(17.34))); Output 578 ## BQN Double ← 2⊸×Halve ← ⌊÷⟜2Odd ← 2⊸| EMul ← { times ← ↕⌈2⋆⁼𝕨 +´(Odd Halve⍟times 𝕨)/Double⍟times 𝕩} 17 EMul 34 578 To avoid using a while loop, the iteration count is computed beforehand. ## C #include <stdio.h>#include <stdbool.h> void halve(int *x) { *x >>= 1; }void doublit(int *x) { *x <<= 1; }bool iseven(const int x) { return (x & 1) == 0; } int ethiopian(int plier, int plicand, const bool tutor){ int result=0; if (tutor) printf("ethiopian multiplication of %d by %d\n", plier, plicand); while(plier >= 1) { if ( iseven(plier) ) { if (tutor) printf("%4d %6d struck\n", plier, plicand); } else { if (tutor) printf("%4d %6d kept\n", plier, plicand); result += plicand; } halve(&plier); doublit(&plicand); } return result;} int main(){ printf("%d\n", ethiopian(17, 34, true)); return 0;} ## C# Works with: C# version 3+ Library: System.Linq  using System;using System.Linq; namespace RosettaCode.Tasks{ public static class EthiopianMultiplication_Task { public static void Test ( ) { Console.WriteLine ( "Ethiopian Multiplication" ); int A = 17, B = 34; Console.WriteLine ( "Recursion: {0}*{1}={2}", A, B, EM_Recursion ( A, B ) ); Console.WriteLine ( "Linq: {0}*{1}={2}", A, B, EM_Linq ( A, B ) ); Console.WriteLine ( "Loop: {0}*{1}={2}", A, B, EM_Loop ( A, B ) ); Console.WriteLine ( ); } public static int Halve ( this int p_Number ) { return p_Number >> 1; } public static int Double ( this int p_Number ) { return p_Number << 1; } public static bool IsEven ( this int p_Number ) { return ( p_Number % 2 ) == 0; } public static int EM_Recursion ( int p_NumberA, int p_NumberB ) { // Anchor Point, Recurse to find the next row Sum it with the second number according to the rules return p_NumberA == 1 ? p_NumberB : EM_Recursion ( p_NumberA.Halve ( ), p_NumberB.Double ( ) ) + ( p_NumberA.IsEven ( ) ? 0 : p_NumberB ); } public static int EM_Linq ( int p_NumberA, int p_NumberB ) { // Creating a range from 1 to x where x the number of times p_NumberA can be halved. // This will be 2^x where 2^x <= p_NumberA. Basically, ln(p_NumberA)/ln(2). return Enumerable.Range ( 1, Convert.ToInt32 ( Math.Log ( p_NumberA, Math.E ) / Math.Log ( 2, Math.E ) ) + 1 ) // For every item (Y) in that range, create a new list, comprising the pair (p_NumberA,p_NumberB) Y times. .Select ( ( item ) => Enumerable.Repeat ( new { Col1 = p_NumberA, Col2 = p_NumberB }, item ) // The aggregate method iterates over every value in the target list, passing the accumulated value and the current item's value. .Aggregate ( ( agg_pair, orig_pair ) => new { Col1 = agg_pair.Col1.Halve ( ), Col2 = agg_pair.Col2.Double ( ) } ) ) // Remove all even items .Where ( pair => !pair.Col1.IsEven ( ) ) // And sum! .Sum ( pair => pair.Col2 ); } public static int EM_Loop ( int p_NumberA, int p_NumberB ) { int RetVal = 0; while ( p_NumberA >= 1 ) { RetVal += p_NumberA.IsEven ( ) ? 0 : p_NumberB; p_NumberA = p_NumberA.Halve ( ); p_NumberB = p_NumberB.Double ( ); } return RetVal; } }} ## C++ Using C++ templates, these kind of tasks can be implemented as meta-programs. The program runs at compile time, and the result is statically saved into regularly compiled code. Here is such an implementation without tutor, since there is no mechanism in C++ to output messages during program compilation. template<int N>struct Half { enum { Result = N >> 1 };}; template<int N>struct Double { enum { Result = N << 1 };}; template<int N>struct IsEven { static const bool Result = (N & 1) == 0;}; template<int Multiplier, int Multiplicand>struct EthiopianMultiplication{ template<bool Cond, int Plier, int RunningTotal> struct AddIfNot { enum { Result = Plier + RunningTotal }; }; template<int Plier, int RunningTotal> struct AddIfNot <true, Plier, RunningTotal> { enum { Result = RunningTotal }; }; template<int Plier, int Plicand, int RunningTotal> struct Loop { enum { Result = Loop<Half<Plier>::Result, Double<Plicand>::Result, AddIfNot<IsEven<Plier>::Result, Plicand, RunningTotal >::Result >::Result }; }; template<int Plicand, int RunningTotal> struct Loop <0, Plicand, RunningTotal> { enum { Result = RunningTotal }; }; enum { Result = Loop<Multiplier, Multiplicand, 0>::Result };}; #include <iostream> int main(int, char **){ std::cout << EthiopianMultiplication<17, 54>::Result << std::endl; return 0;} ## Clojure (defn halve [n] (bit-shift-right n 1)) (defn twice [n] ; 'double' is taken (bit-shift-left n 1)) (defn even [n] ; 'even?' is the standard fn (zero? (bit-and n 1))) (defn emult [x y] (reduce + (map second (filter #(not (even (first %))) ; a.k.a. 'odd?' (take-while #(pos? (first %)) (map vector (iterate halve x) (iterate twice y))))))) (defn emult2 [x y] (loop [a x, b y, r 0] (if (= a 1) (+ r b) (if (even a) (recur (halve a) (twice b) r) (recur (halve a) (twice b) (+ r b)))))) ## CLU halve = proc (n: int) returns (int) return(n/2)end halve double = proc (n: int) returns (int) return(n*2)end double even = proc (n: int) returns (bool) return(n//2 = 0)end even e_mul = proc (a, b: int) returns (int) total: int := 0 while (a > 0) do if ~even(a) then total := total + b end a := halve(a) b := double(b) end return(total)end e_mul start_up = proc () po: stream := stream$primary_output()    stream$putl(po, int$unparse(e_mul(17, 34)))end start_up
Output:
578

## COBOL

Translation of: Common Lisp
Works with: COBOL version 2002
Works with: OpenCOBOL version 1.1

In COBOL, double is a reserved word, so the doubling functions is named twice, instead.

       *>* Ethiopian multiplication        IDENTIFICATION DIVISION.       PROGRAM-ID. ethiopian-multiplication.       DATA DIVISION.       LOCAL-STORAGE SECTION.       01  l                  PICTURE 9(10) VALUE 17.       01  r                  PICTURE 9(10) VALUE 34.       01  ethiopian-multiply PICTURE 9(20).       01  product            PICTURE 9(20).       PROCEDURE DIVISION.         CALL "ethiopian-multiply" USING           BY CONTENT l, BY CONTENT r,           BY REFERENCE ethiopian-multiply         END-CALL         DISPLAY ethiopian-multiply END-DISPLAY         MULTIPLY l BY r GIVING product END-MULTIPLY         DISPLAY product END-DISPLAY         STOP RUN.       END PROGRAM ethiopian-multiplication.        IDENTIFICATION DIVISION.       PROGRAM-ID. ethiopian-multiply.       DATA DIVISION.       LOCAL-STORAGE SECTION.       01  evenp   PICTURE 9.         88 even   VALUE 1.         88 odd    VALUE 0.       LINKAGE SECTION.       01  l       PICTURE 9(10).       01  r       PICTURE 9(10).       01  product PICTURE 9(20) VALUE ZERO.       PROCEDURE DIVISION using l, r, product.         MOVE ZEROES TO product         PERFORM UNTIL l EQUAL ZERO           CALL "evenp" USING             BY CONTENT l,             BY REFERENCE evenp           END-CALL           IF odd             ADD r TO product GIVING product END-ADD           END-IF           CALL "halve" USING             BY CONTENT l,             BY REFERENCE l           END-CALL           CALL "twice" USING             BY CONTENT r,             BY REFERENCE r           END-CALL         END-PERFORM         GOBACK.       END PROGRAM ethiopian-multiply.        IDENTIFICATION DIVISION.       PROGRAM-ID. halve.       DATA DIVISION.       LOCAL-STORAGE SECTION.       LINKAGE SECTION.       01  n   PICTURE 9(10).       01  m   PICTURE 9(10).       PROCEDURE DIVISION USING n, m.         DIVIDE n BY 2 GIVING m END-DIVIDE         GOBACK.       END PROGRAM halve.        IDENTIFICATION DIVISION.       PROGRAM-ID. twice.       DATA DIVISION.       LOCAL-STORAGE SECTION.       LINKAGE SECTION.       01  n   PICTURE 9(10).       01  m   PICTURE 9(10).       PROCEDURE DIVISION USING n, m.         MULTIPLY n by 2 GIVING m END-MULTIPLY         GOBACK.       END PROGRAM twice.        IDENTIFICATION DIVISION.       PROGRAM-ID. evenp.       DATA DIVISION.       LOCAL-STORAGE SECTION.       01  q   PICTURE 9(10).       LINKAGE SECTION.       01  n   PICTURE 9(10).       01  m   PICTURE 9(1).         88 even   VALUE 1.         88 odd    VALUE 0.       PROCEDURE DIVISION USING n, m.         DIVIDE n BY 2 GIVING q REMAINDER m END-DIVIDE         SUBTRACT m FROM 1 GIVING m END-SUBTRACT         GOBACK.       END PROGRAM evenp.

## CoffeeScript

 halve = (n) -> Math.floor n / 2double = (n) -> n * 2is_even = (n) -> n % 2 == 0 multiply = (a, b) ->  prod = 0  while a > 0    prod += b if !is_even a    a = halve a    b = double b  prod # testsdo ->  for i in [0..100]    for j in [0..100]      throw Error("broken for #{i} * #{j}") if multiply(i,j) != i * j 

## ColdFusion

Version with as a function of functions:

<cffunction name="double">    <cfargument name="number" type="numeric" required="true">	<cfset answer = number * 2>    <cfreturn answer></cffunction> <cffunction name="halve">    <cfargument name="number" type="numeric" required="true">	<cfset answer = int(number / 2)>    <cfreturn answer></cffunction> <cffunction name="even">    <cfargument name="number" type="numeric" required="true">	<cfset answer = number mod 2>    <cfreturn answer></cffunction> <cffunction name="ethiopian">    <cfargument name="Number_A" type="numeric" required="true">    <cfargument name="Number_B" type="numeric" required="true">    <cfset Result = 0>     <cfloop condition = "Number_A GTE 1">        <cfif even(Number_A) EQ 1>            <cfset Result = Result + Number_B>        </cfif>        <cfset Number_A = halve(Number_A)>        <cfset Number_B = double(Number_B)>    </cfloop>    <cfreturn Result>  </cffunction>  <cfoutput>#ethiopian(17,34)#</cfoutput>
Version with display pizza:
<cfset Number_A = 17><cfset Number_B = 34><cfset Result = 0> <cffunction name="double">    <cfargument name="number" type="numeric" required="true">	<cfset answer = number * 2>    <cfreturn answer></cffunction> <cffunction name="halve">    <cfargument name="number" type="numeric" required="true">	<cfset answer = int(number / 2)>    <cfreturn answer></cffunction> <cffunction name="even">    <cfargument name="number" type="numeric" required="true">	<cfset answer = number mod 2>    <cfreturn answer></cffunction>  <cfoutput> Ethiopian multiplication of #Number_A# and #Number_B#...<br>  <table width="512" border="0" cellspacing="20" cellpadding="0"> <cfloop condition = "Number_A GTE 1">     <cfif even(Number_A) EQ 1>   	<cfset Result = Result + Number_B>        <cfset Action = "Keep">   <cfelse>	<cfset Action = "Strike">   </cfif>   <tr>    <td align="right">#Number_A#</td>    <td align="right">#Number_B#</td>    <td align="center">#Action#</td>  </tr>   <cfset Number_A = halve(Number_A)>  <cfset Number_B = double(Number_B)> </cfloop>   </table> ...equals #Result# </cfoutput>
Sample output:
Ethiopian multiplication of 17 and 34...
17 	34 	Keep
8 	68 	Strike
4 	136 	Strike
2 	272 	Strike
1 	544 	Keep
...equals 578


## Common Lisp

Common Lisp already has evenp, but all three of halve, double, and even-p are locally defined within ethiopian-multiply. (Note that the termination condition is (zerop l) because we terminate 'after' the iteration wherein the left column contains 1, and (halve 1) is 0.)
(defun ethiopian-multiply (l r)  (flet ((halve (n) (floor n 2))         (double (n) (* n 2))         (even-p (n) (zerop (mod n 2))))    (do ((product 0 (if (even-p l) product (+ product r)))         (l l (halve l))         (r r (double r)))        ((zerop l) product))))

## D

int ethiopian(int n1, int n2) pure nothrow @nogcin {    assert(n1 >= 0, "Multiplier can't be negative");} body {    static enum doubleNum = (in int n) pure nothrow @nogc => n * 2;    static enum halveNum = (in int n) pure nothrow @nogc => n / 2;    static enum isEven = (in int n) pure nothrow @nogc => !(n & 1);     int result;    while (n1 >= 1) {        if (!isEven(n1))            result += n2;        n1 = halveNum(n1);        n2 = doubleNum(n2);    }     return result;} unittest {    assert(ethiopian(77, 54) == 77 * 54);    assert(ethiopian(8, 923) == 8 * 923);    assert(ethiopian(64, -4) == 64 * -4);} void main() {    import std.stdio;     writeln("17 ethiopian 34 is ", ethiopian(17, 34));}
Output:
17 ethiopian 34 is 578


## dc

0k                    [ Make sure we're doing integer division  ]sx[ 2 / ] sH            [ Define "halve" function in register H   ]sx[ 2 * ] sD            [ Define "double" function in register D  ]sx[ 2 % 1 r - ] sE      [ Define "even?" function in register E   ]sx [ Entry into the main Ethiopian multiplication function is register M ]sx[ Keeps running value for the product in register p ]sx[ 0 sp lLx lp ] sM [ The body of the main loop is in register L ]sx [   sb sa             [ First thing we do is cheat and store the parameters in                      registers, which is safe because the only recursion is of                      the tail variety.  This avoids tricky stack                      manipulations, which dc doesn't have good support for                      (unlike, say, Forth). ]sx   la lEx sr         [ r = even?(a)  ]sx  lr 0 =S           [ if r = 0 then call s]sx  la lHx d          [ a = halve(a)]sx  lb lDx            [ b = double(b)]sx  r 0 !=L           [ if a !=0 then recurse ]] sL [ Utility macro that just adds the current value of b to the total in p ]sx[ lp lb + sp ]sS [ Demo by multiplying 17 and 34 ]sx17 34 lMx p
Output:
578


See Pascal.

## Draco

proc nonrec halve(word n) word:  n >> 1     corpproc nonrec double(word n) word: n << 1     corpproc nonrec even(word n) bool:   n & 1 = 0  corp proc nonrec emul(word a, b) word:    word total;    total := 0;    while a > 0 do        if not even(a) then total := total + b fi;        a := halve(a);        b := double(b)    od;    totalcorp proc nonrec main() void: writeln(emul(17, 34)) corp
Output:
578

## E

def halve(&x)  { x //= 2 }def double(&x) { x *= 2 }def even(x)    { return x %% 2 <=> 0 } def multiply(var a, var b) {    var ab := 0    while (a > 0) {        if (!even(a)) { ab += b }        halve(&a)        double(&b)    }    return ab}

## EasyLang

Translation of: Microsoft Small Basic
x = 17y = 34tot = 0while x >= 1  write x  write "\t"  if (x + 1) mod 2 = 0    tot += y    print y  else    print ""  .  x = x div 2  y = 2 * y.write "=\t"print tot

## Eiffel

 class	APPLICATION create	make feature {NONE} 	make		do			io.put_integer (ethiopian_multiplication (17, 34))		end 	ethiopian_multiplication (a, b: INTEGER): INTEGER			-- Product of 'a' and 'b'.		require			a_positive: a > 0			b_positive: b > 0		local			x, y: INTEGER		do			x := a			y := b			from			until				x <= 0			loop				if not is_even_int (x) then					Result := Result + y				end				x := halve_int (x)				y := double_int (y)			end		ensure			Result_correct: Result = a * b		end feature {NONE} 	double_int (n: INTEGER): INTEGER                        --Two times 'n'.		do			Result := n * 2		end 	halve_int (n: INTEGER): INTEGER                        --'n' divided by two.		do			Result := n // 2		end 	is_even_int (n: INTEGER): BOOLEAN                        --Is 'n' an even integer?		do			Result := n \\ 2 = 0		end end  
Output:
578


## Ela

open list number halve x = x div 2double = (2*) ethiopicmult a b = sum <| map snd <| filter (odd << fst) <| zip  (takeWhile (>=1) <| iterate halve a)  (iterate double b) ethiopicmult 17 34
Output:
578


## Elixir

Translation of: Erlang
defmodule Ethiopian do  def halve(n), do: div(n, 2)   def double(n), do: n * 2   def even(n), do: rem(n, 2) == 0   def multiply(lhs, rhs) when is_integer(lhs) and lhs > 0 and is_integer(rhs) and rhs > 0 do    multiply(lhs, rhs, 0)  end   def multiply(1, rhs, acc), do: rhs + acc  def multiply(lhs, rhs, acc) do    if even(lhs), do:   multiply(halve(lhs), double(rhs), acc),                  else: multiply(halve(lhs), double(rhs), acc+rhs)  endend IO.inspect Ethiopian.multiply(17, 34)
Output:
578


## Emacs Lisp

Emacs Lisp has cl-evenp in cl-lib.el (its Common Lisp library), but for the sake of completeness the desired effect is achieved here via mod.

 (defun even-p (n)  (= (mod n 2) 0))(defun halve (n)  (floor n 2))(defun double (n)  (* n 2))(defun ethiopian-multiplication (l r)  (let ((sum 0))    (while (>= l 1)      (unless (even-p l)	(setq sum (+ r sum)))      (setq l (halve l))      (setq r (double r)))    sum)) 

## Erlang

-module(ethopian).-export([multiply/2]). halve(N) ->    N div 2. double(N) ->    N * 2. even(N) ->    (N rem 2) == 0. multiply(LHS,RHS) when is_integer(Lhs) and Lhs > 0 and			is_integer(Rhs) and Rhs > 0 ->    multiply(LHS,RHS,0). multiply(1,RHS,Acc) ->    RHS+Acc;multiply(LHS,RHS,Acc) ->    case even(LHS) of        true ->            multiply(halve(LHS),double(RHS),Acc);        false ->            multiply(halve(LHS),double(RHS),Acc+RHS)    end.

## ERRE

PROGRAM ETHIOPIAN_MULT FUNCTION EVEN(A)   EVEN=(A+1) MOD 2END FUNCTION FUNCTION HALF(A)   HALF=INT(A/2)END FUNCTION FUNCTION DOUBLE(A)   DOUBLE=2*AEND FUNCTION BEGIN   X=17 Y=34 TOT=0   WHILE X>=1 DO     PRINT(X,)     IF EVEN(X)=0 THEN TOT=TOT+Y PRINT(Y) ELSE PRINT END IF     X=HALF(X) Y=DOUBLE(Y)   END WHILE   PRINT("=",TOT)END PROGRAM 
Output:
17            34
8
4
2
1             544
=             578


## Euphoria

function emHalf(integer n)  return floor(n/2)end function function emDouble(integer n)  return n*2end function function emIsEven(integer n)  return (remainder(n,2) = 0)end function function emMultiply(integer a, integer b) integer sum  sum = 0  while (a) do    if (not emIsEven(a)) then sum += b end if    a = emHalf(a)    b = emDouble(b)  end while   return sumend function ------------------------------------------------------------------ runtime printf(1,"emMultiply(%d,%d) = %d\n",{17,34,emMultiply(17,34)}) printf(1,"\nPress Any Key\n",{})while (get_key() = -1) do end while

## F#

let ethopian n m =    let halve n = n / 2    let double n = n * 2    let even n = n % 2 = 0    let rec loop n m result =        if n <= 1 then result + m        else if even n then loop (halve n) (double m) result        else loop (halve n) (double m) (result + m)    loop n m 0

## Factor

USING: arrays kernel math multiline sequences ;IN: ethiopian-multiplication /*This function is built-in: odd? ( n -- ? ) 1 bitand 1 number= ;*/ : double ( n -- 2*n ) 2 * ;: halve ( n -- n/2 ) 2 /i ; : ethiopian-mult ( a b -- a*b )    [ 0 ] 2dip    [ dup 0 > ] [        [ odd? [ + ] [ drop ] if ] 2keep        [ double ] [ halve ] bi*    ] while 2drop ;

## FALSE

[2/]h:[2*]d:[$2/2*-]o:[0[@$][$o;![@@\[email protected][email protected]]?h;[email protected];[email protected]]#%\%]m:17 34m;!. {578} ## Forth Halve and double are standard words, spelled 2/ and 2* respectively. : even? ( n -- ? ) 1 and 0= ;: e* ( x y -- x*y ) dup 0= if nip exit then over 2* over 2/ recurse swap even? if nip else + then ; The author of Forth, Chuck Moore, designed a similar primitive into his MISC Forth microprocessors. The +* instruction is a multiply step: it adds S to T if A is odd, then shifts both A and T right one. The idea is that you only need to perform as many of these multiply steps as you have significant bits in the operand.(See his core instruction set for details.) ## Fortran Works with: Fortran version 90 and later program EthiopicMult implicit none print *, ethiopic(17, 34, .true.) contains subroutine halve(v) integer, intent(inout) :: v v = int(v / 2) end subroutine halve subroutine doublit(v) integer, intent(inout) :: v v = v * 2 end subroutine doublit function iseven(x) logical :: iseven integer, intent(in) :: x iseven = mod(x, 2) == 0 end function iseven function ethiopic(multiplier, multiplicand, tutorialized) result(r) integer :: r integer, intent(in) :: multiplier, multiplicand logical, intent(in), optional :: tutorialized integer :: plier, plicand logical :: tutor plier = multiplier plicand = multiplicand if ( .not. present(tutorialized) ) then tutor = .false. else tutor = tutorialized endif r = 0 if ( tutor ) write(*, '(A, I0, A, I0)') "ethiopian multiplication of ", plier, " by ", plicand do while(plier >= 1) if ( iseven(plier) ) then if (tutor) write(*, '(I4, " ", I6, A)') plier, plicand, " struck" else if (tutor) write(*, '(I4, " ", I6, A)') plier, plicand, " kept" r = r + plicand endif call halve(plier) call doublit(plicand) end do end function ethiopic end program EthiopicMult ## Fōrmulæ Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition. Programs in Fōrmulæ are created/edited online in its website, However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used. In this page you can see the program(s) related to this task and their results. ## Go package main import "fmt" func halve(i int) int { return i/2 } func double(i int) int { return i*2 } func isEven(i int) bool { return i%2 == 0 } func ethMulti(i, j int) (r int) { for ; i > 0; i, j = halve(i), double(j) { if !isEven(i) { r += j } } return} func main() { fmt.Printf("17 ethiopian 34 = %d\n", ethMulti(17, 34))} ## Haskell ### Using integer (+) import Prelude hiding (odd)import Control.Monad (join) halve :: Int -> Inthalve = (div 2) double :: Int -> Intdouble = join (+) odd :: Int -> Boolodd = (== 1) . (mod 2) ethiopicmult :: Int -> Int -> Intethiopicmult a b = sum$  map snd $filter (odd . fst)$  zip (takeWhile (>= 1) $iterate halve a) (iterate double b) main :: IO ()main = print$ ethiopicmult 17 34 == 17 * 34
Output:
*Main> ethiopicmult 17 34
578

### Fold after unfold

Logging the stages of the unfoldr and foldr applications:

import Data.List (inits, intercalate, unfoldr)import Data.Tuple (swap)import Debug.Trace (trace) ----------------- ETHIOPIAN MULTIPLICATION --------------- ethMult :: Int -> Int -> IntethMult n m =  ( trace      =<< (<> "\n")        . ((showDoubles pairs <> " = ") <>)        . show  )    (foldr addedWhereOdd 0 pairs)  where    pairs = zip (unfoldr halved n) (iterate doubled m)    doubled x = x + x    halved h      | 0 < h =        Just $trace (showHalf h) (swap$ quotRem h 2)      | otherwise = Nothing     addedWhereOdd (d, x) a      | 0 < d = (+) a x      | otherwise = a ---------------------- TRACE DISPLAY --------------------- showHalf :: Int -> StringshowHalf x = "halve: " <> rjust 6 ' ' (show (quotRem x 2)) showDoubles :: [(Int, Int)] -> StringshowDoubles xs =  "double:\n"    <> unlines (go <$> xs) <> intercalate " + " (xs >>= f) where go x | 0 < fst x = "-> " <> rjust 3 ' ' (show$ snd x)      | otherwise = rjust 6 ' ' $show$ snd x    f (r, q)      | 0 < r = [show q]      | otherwise = [] rjust :: Int -> Char -> String -> Stringrjust n c s = drop (length s) (replicate n c <> s) --------------------------- TEST -------------------------main :: IO ()main = do  print $ethMult 17 34 print$ ethMult 34 17
Output:
halve:  (8,1)
halve:  (4,0)
halve:  (2,0)
halve:  (1,0)
halve:  (0,1)
double:
->  34
68
136
272
-> 544
34 + 544 = 578

halve: (17,0)
halve:  (8,1)
halve:  (4,0)
halve:  (2,0)
halve:  (1,0)
halve:  (0,1)
double:
17
->  34
68
136
272
-> 544
34 + 544 = 578

578
578

### Using monoid mappend

Alternatively, we can express Ethiopian multiplication in terms of mappend and mempty, in place of (+) and 0.

This additional generality means that our ethMult function can now replicate a string n times as readily as it multiplies an integer n times, or raises an integer to the nth power.

import Control.Monad (join)import Data.List (unfoldr)import Data.Monoid (getProduct, getSum)import Data.Tuple (swap) ----------------- ETHIOPIAN MULTIPLICATION ---------------ethMult ::  (Monoid m) =>  Int ->  m ->  methMult n m =  foldr addedWhereOdd mempty $zip (unfoldr half n)$ iterate (join (<>)) m  where    half n      | 0 /= n = Just . swap $quotRem n 2 | otherwise = Nothing addedWhereOdd (d, x) a | 0 /= d = a <> x | otherwise = a --------------------------- TEST -------------------------main :: IO ()main = do mapM_ print$    [ getSum $ethMult 17 34, -- 34 * 17 getProduct$ ethMult 3 34 -- 34 ^ 3    ]      -- [3 ^ 17, 4 ^ 17]      <> (getProduct <$> ([ethMult 17] <*> [3, 4])) print$ ethMult 17 "34"  print $ethMult 17 [3, 4] Output: 578 39304 129140163 17179869184 "3434343434343434343434343434343434" [3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4] ## HicEst  WRITE(Messagebox) ethiopian( 17, 34 )END ! of "main" FUNCTION ethiopian(x, y) ethiopian = 0 left = x right = y DO i = x, 1, -1 IF( isEven(left) == 0 ) ethiopian = ethiopian + right IF( left == 1 ) RETURN left = halve(left) right = double(right) ENDDO END FUNCTION halve( x ) halve = INT( x/2 ) END FUNCTION double( x ) double = 2 * x END FUNCTION isEven( x ) isEven = MOD(x, 2) == 0 END  ## Icon and Unicon procedure main(arglist)while ethiopian(integer(get(arglist)),integer(get(arglist))) # multiply successive pairs of command line argumentsend procedure ethiopian(i,j) # recursive Ethiopian multiplicationreturn ( if not even(i) then j # this exploits that icon control expressions return values else 0 ) + ( if i ~= 0 then ethiopian(halve(i),double(j)) else 0 )end procedure double(i)return i * 2end procedure halve(i)return i / 2end procedure even(i)return ( i % 2 = 0, i )end While not it seems a task requirement, most implementations have a tutorial version. This seemed easiest in an iterative version. procedure ethiopian(i,j) # iterative tutorlocal p,ww := *j+3write("Ethiopian Multiplication of ",i," * ",j) p := 0until i = 0 do { writes(right(i,w),right(j,w)) if not even(i) then { p +:= j write(" add") } else write(" discard") i := halve(i) j := double(j) }write(right("=",w),right(p,w))return pend ## J Solution: double =: 2&*halve =: %&2 NB. or the primitive -:odd =: 2&| ethiop =: +/@([email protected]] # (double~ <@#)) (1>.<[email protected])^:a: Example:  17 ethiop 34 578  Note that double will repeatedly double its right argument if given a repetition count for its left argument:  (<5) double 17 17 34 68 136 272  Note: this implementation assumes that the number on the right is a positive integer. In contexts where it can be negative, its absolute value should be used and you should multiply the result of ethiop by its sign. ethio=: *@] * (ethiop |) Alternatively, if multiplying by negative 1 is prohibited, you can use a conditional function which optionally negates its argument. ethio=: *@] [email protected]]^:(0 > [) (ethiop |) Examples:  7 ethio 1177 7 ethio _11_77 _7 ethio 11_77 _7 ethio _1177 ## Java Works with: Java version 1.5+ import java.util.HashMap;import java.util.Map;import java.util.Scanner;public class Mult{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int first = sc.nextInt(); int second = sc.nextInt(); if(first < 0){ first = -first; second = -second; } Map<Integer, Integer> columns = new HashMap<Integer, Integer>(); columns.put(first, second); int sum = isEven(first)? 0 : second; do{ first = halveInt(first); second = doubleInt(second); columns.put(first, second); if(!isEven(first)){ sum += second; } }while(first > 1); System.out.println(sum); } public static int doubleInt(int doubleMe){ return doubleMe << 1; //shift left } public static int halveInt(int halveMe){ return halveMe >>> 1; //shift right } public static boolean isEven(int num){ return (num & 1) == 0; }} An optimised variant using the three helper functions from the other example. /** * This method will use ethiopian styled multiplication. * @param a Any non-negative integer. * @param b Any integer. * @result a multiplied by b */public static int ethiopianMultiply(int a, int b) { if(a==0 || b==0) { return 0; } int result = 0; while(a>=1) { if(!isEven(a)) { result+=b; } b = doubleInt(b); a = halveInt(a); } return result;} /** * This method is an improved version that will use * ethiopian styled multiplication, and also * supports negative parameters. * @param a Any integer. * @param b Any integer. * @result a multiplied by b */public static int ethiopianMultiplyWithImprovement(int a, int b) { if(a==0 || b==0) { return 0; } if(a<0) { a=-a; b=-b; } else if(b>0 && a>b) { int tmp = a; a = b; b = tmp; } int result = 0; while(a>=1) { if(!isEven(a)) { result+=b; } b = doubleInt(b); a = halveInt(a); } return result;} ## JavaScript var eth = { halve : function ( n ){ return Math.floor(n/2); }, double: function ( n ){ return 2*n; }, isEven: function ( n ){ return n%2 === 0); }, mult: function ( a , b ){ var sum = 0, a = [a], b = [b]; while ( a[0] !== 1 ){ a.unshift( eth.halve( a[0] ) ); b.unshift( eth.double( b[0] ) ); } for( var i = a.length - 1; i > 0 ; i -= 1 ){ if( !eth.isEven( a[i] ) ){ sum += b[i]; } } return sum + b[0]; }}// eth.mult(17,34) returns 578 Or, avoiding the use of a multiplication operator in the version above, we can alternatively: 1. Halve an integer, in this sense, with a right-shift (n >>= 1) 2. Double an integer by addition to self (m += m) 3. Test if an integer is odd by bitwise and (n & 1) function ethMult(m, n) { var o = !isNaN(m) ? 0 : ''; // same technique works with strings if (n < 1) return o; while (n > 1) { if (n & 1) o += m; // 3. integer odd/even? (bit-wise and 1) n >>= 1; // 1. integer halved (by right-shift) m += m; // 2. integer doubled (addition to self) } return o + m;} ethMult(17, 34) Output: 578 Note that the same function will also multiply strings with some efficiency, particularly where n is larger. See Repeat_a_string ethMult('Ethiopian', 34) Output: "EthiopianEthiopianEthiopianEthiopianEthiopianEthiopian EthiopianEthiopianEthiopianEthiopianEthiopianEthiopianEthiopian EthiopianEthiopianEthiopianEthiopianEthiopianEthiopianEthiopian EthiopianEthiopianEthiopianEthiopianEthiopianEthiopianEthiopian EthiopianEthiopianEthiopianEthiopianEthiopianEthiopianEthiopian" ## jq The following implementation is intended for jq 1.4 and later. If your jq has while/2, then the implementation of the inner function, pairs, can be simplified to: def pairs: while( .[0] > 0; [ (.[0] | halve), (.[1] | double) ]); def halve: (./2) | floor; def double: 2 * .; def isEven: . % 2 == 0; def ethiopian_multiply(a;b): def pairs: recurse( if .[0] > 0 then [ (.[0] | halve), (.[1] | double) ] else empty end ); reduce ([a,b] | pairs | select( .[0] | isEven | not) | .[1] ) as$i    (0; . + $i) ; Example: ethiopian_multiply(17;34) # => 578 ## Jsish From Javascript entry. /* Ethiopian multiplication in Jsish */var eth = { halve : function(n) { return Math.floor(n / 2); }, double: function(n) { return n << 1; }, isEven: function(n) { return n % 2 === 0; }, mult: function(a, b){ var sum = 0; a = [a], b = [b]; while (a[0] !== 1) { a.unshift(eth.halve(a[0])); b.unshift(eth.double(b[0])); } for (var i = a.length - 1; i > 0; i -= 1) { if(!eth.isEven(a[i])) sum += b[i]; } return sum + b[0]; }}; ;eth.mult(17,34); /*=!EXPECTSTART!=eth.mult(17,34) ==> 578=!EXPECTEND!=*/ Output: prompt$ jsish -u ethiopianMultiplication.jsi
[PASS] ethiopianMultiplication.jsi

## Julia

Works with: Julia version 0.6

Helper functions (type stable):

halve(x::Integer) = x >> one(x)double(x::Integer) = Int8(2) * xeven(x::Integer) = x & 1 != 1

Main function:

function ethmult(a::Integer, b::Integer)    r = 0    while a > 0        r += b * !even(a)        a = halve(a)        b = double(b)    end    return rend @show ethmult(17, 34)

Array version (more similar algorithm to the one from the task description):

function ethmult2(a::Integer, b::Integer)    A = [a]    B = [b]    while A[end] > 1        push!(A, halve(A[end]))        push!(B, double(B[end]))    end    return sum(B[map(!even, A)])end @show ethmult2(17, 34)
Output:
ethmult(17, 34) = 578
ethmult2(17, 34) = 578

Benchmark test:

julia> @time ethmult(17, 34)
0.000003 seconds (5 allocations: 176 bytes)
578

julia> @time ethmult2(17, 34)
0.000007 seconds (18 allocations: 944 bytes)
578


## Kotlin

// version 1.1.2 fun halve(n: Int) = n / 2 fun double(n: Int) = n * 2 fun isEven(n: Int) = n % 2 == 0 fun ethiopianMultiply(x: Int, y: Int): Int {    var xx = x    var yy = y    var sum = 0    while (xx >= 1) {       if (!isEven(xx)) sum += yy       xx = halve(xx)       yy = double(yy)    }    return sum} fun main(args: Array<String>) {    println("17 x 34 = ${ethiopianMultiply(17, 34)}") println("99 x 99 =${ethiopianMultiply(99, 99)}")}
Output:
17 x 34 = 578
99 x 99 = 9801


## Lambdatalk

A translation from the javascript entry.

 {def halve {lambda {:n} {floor {/ :n 2}}}} -> halve{def double {lambda {:n} {* 2 :n}}} -> double{def isEven {lambda {:n} {= {% :n 2} 0}}} -> isEven {def mult   {def mult.r  {lambda {:a :b}   {if {= {A.first :a} 1}    then {+ {S.map {{lambda {:a :b :i}                    {if {isEven {A.get :i :a}}                     then else {A.get :i :b}}} :a :b}                   {S.serie {- {A.length :a} 1} 0 -1}}}     else {mult.r {A.addfirst! {halve {A.first :a}} :a}                 {A.addfirst! {double {A.first :b}} :b}}}}}  {lambda {:a :b}  {mult.r {A.new :a} {A.new :b}}}}-> mult {mult 17 34}-> 578  

## Limbo

implement Ethiopian; include "sys.m";	sys: Sys;	print: import sys;include "draw.m";	draw: Draw; Ethiopian : module{	init : fn(ctxt : ref Draw->Context, args : list of string);}; init (ctxt: ref Draw->Context, args: list of string){	sys = load Sys Sys->PATH; 	print("\n%d\n", ethiopian(17, 34, 0));	print("\n%d\n", ethiopian(99, 99, 1));} halve(n: int): int{	return (n /2);} double(n: int): int{	return (n * 2);} iseven(n: int): int{	return ((n%2) == 0);} ethiopian(a: int, b: int, tutor: int): int{	product := 0;	if (tutor)		print("\nmultiplying %d x %d", a, b);	while (a >= 1) {		if (!(iseven(a))) {			if (tutor)				print("\n%3d   %d", a, b);			product += b;		} else			if (tutor)				print("\n%3d   ----", a);		a = halve(a);		b = double(b);	}	return product;} 

## Locomotive Basic

10 DEF FNiseven(a)=(a+1) MOD 220 DEF FNhalf(a)=INT(a/2)30 DEF FNdouble(a)=2*a40 x=17:y=34:tot=050 WHILE x>=160 PRINT x,70 IF FNiseven(x)=0 THEN tot=tot+y:PRINT y ELSE PRINT80 x=FNhalf(x):y=FNdouble(y)90 WEND100 PRINT "=", tot

Output:

 17           34
8
4
2
1            544
=             578


## Logo

to double :x  output ashift :x  1endto halve :x  output ashift :x -1endto even? :x  output equal? 0 bitand 1 :xendto eproduct :x :y  if :x = 0 [output 0]  ifelse even? :x ~    [output      eproduct halve :x double :y] ~    [output :y + eproduct halve :x double :y]end

## LOLCODE

HAI 1.3 HOW IZ I Halve YR Integer  FOUND YR QUOSHUNT OF Integer AN 2IF U SAY SO HOW IZ I Dubble YR Integer  FOUND YR PRODUKT OF Integer AN 2IF U SAY SO HOW IZ I IzEven YR Integer  FOUND YR BOTH SAEM 0 AN MOD OF Integer AN 2IF U SAY SO HOW IZ I EthiopianProdukt YR a AN YR b  I HAS A Result ITZ 0  IM IN YR LOOP UPPIN YR x WILE DIFFRINT a AN 0    NOT I IZ IzEven YR a MKAY    O RLY?      YA RLY        Result R SUM OF Result AN b    OIC    a R I IZ Halve YR a MKAY    b R I IZ Dubble YR b MKAY  IM OUTTA YR LOOP  FOUND YR ResultIF U SAY SO VISIBLE I IZ EthiopianProdukt YR 17 AN YR 34 MKAYKTHXBYE
Output:
578

## Lua

function halve(a)    return a/2end function double(a)    return a*2end function isEven(a)    return a%2 == 0end function ethiopian(x, y)    local result = 0     while (x >= 1) do        if not isEven(x) then            result = result + y        end         x = math.floor(halve(x))        y = double(y)    end     return result;end print(ethiopian(17, 34))

## Perl

use strict; sub halve { int((shift) / 2); }sub double { (shift) * 2; }sub iseven { ((shift) & 1) == 0; } sub ethiopicmult{    my ($plier,$plicand, $tutor) = @_; print "ethiopic multiplication of$plier and $plicand\n" if$tutor;    my $r = 0; while ($plier >= 1)    {	$r +=$plicand unless iseven($plier); if ($tutor) {	    print "$plier,$plicand ", (iseven($plier) ? " struck" : " kept"), "\n"; }$plier = halve($plier);$plicand = double($plicand); } return$r;} print ethiopicmult(17,34, 1), "\n";

## Phix

Translation of: Euphoria
function emHalf(integer n)
return floor(n/2)
end function

function emDouble(integer n)
return n*2
end function

function emIsEven(integer n)
return (remainder(n,2)=0)
end function

function emMultiply(integer a, integer b)
integer sum = 0
while a!=0 do
if not emIsEven(a) then sum += b end if
a = emHalf(a)
b = emDouble(b)
end while
return sum
end function

printf(1,"emMultiply(%d,%d) = %d\n",{17,34,emMultiply(17,34)})


## PHP

Not object oriented version:
<?phpfunction halve($x){ return floor($x/2);} function double($x){ return$x*2;} function iseven($x){ return !($x & 0x1);} function ethiopicmult($plier,$plicand, $tutor){ if ($tutor) echo "ethiopic multiplication of $plier and$plicand\n";  $r = 0; while($plier >= 1) {    if ( !iseven($plier) )$r += $plicand; if ($tutor)      echo "$plier,$plicand ", (iseven($plier) ? "struck" : "kept"), "\n";$plier = halve($plier);$plicand = double($plicand); } return$r;} echo ethiopicmult(17, 34, true), "\n"; ?>
Output:
ethiopic multiplication of 17 and 34
17, 34 kept
8, 68 struck
4, 136 struck
2, 272 struck
1, 544 kept
578


Object Oriented version:

Works with: PHP5
<?php class ethiopian_multiply {    protected $result = 0; protected function __construct($x, $y){ while($x >= 1){         $this->sum_result($x, $y);$x = $this->half_num($x);         $y =$this->double_num($y); } } protected function half_num($x){      return floor($x/2); } protected function double_num($y){      return $y*2; } protected function not_even($n){      return $n%2 != 0 ? true : false; } protected function sum_result($x, $y){ if($this->not_even($x)){$this->result += $y; } } protected function get_result(){ return$this->result;   }    static public function init($x,$y){      $init = new ethiopian_multiply($x, $y); return$init->get_result();   } } echo ethiopian_multiply::init(17, 34);?>

## PicoLisp

(de halve (N)   (/ N 2) ) (de double (N)   (* N 2) ) (de even? (N)   (not (bit? 1 N)) ) (de ethiopian (X Y)   (let R 0      (while (>= X 1)         (or (even? X) (inc 'R Y))         (setq            X (halve X)            Y (double Y) ) )      R ) )

## Pike

int ethopian_multiply(int l, int r){    int halve(int n) { return n/2; };    int double(int n) { return n*2; };    int(0..1) evenp(int n) { return !(n%2); };     int product = 0;    do    {        write("%5d %5d\n", l, r);        if (!evenp(l))            product += r;        l = halve(l);        r = double(r);              }    while(l);    return product;}

## PL/I

    declare (L(30), R(30)) fixed binary;   declare (i, s) fixed binary;    L, R = 0;   put skip list      ('Hello, please type two values and I will print their product:');   get list (L(1), R(1));   put edit ('The product of ', trim(L(1)), ' and ', trim(R(1)), ' is ') (a);   do i = 1 by 1 while (L(i) ^= 0);      L(i+1) = halve(L(i));      R(i+1) = double(R(i));   end;   s = 0;   do i = 1 by 1 while (L(i) > 0);      if odd(L(i)) then s = s + R(i);   end;   put edit (trim(s)) (a); halve: procedure (k) returns (fixed binary);   declare k fixed binary;   return (k/2);end halve;double: procedure (k) returns (fixed binary);   declare k fixed binary;   return (2*k);end;odd: procedure (k) returns (bit (1));   return (iand(k, 1) ^= 0);end odd;

## PL/SQL

This code was taken from the ADA example above - very minor differences.

CREATE OR REPLACE PACKAGE ethiopian IS   FUNCTION multiply    ( left    IN  INTEGER,      right   IN  INTEGER)  RETURN INTEGER; END ethiopian;/ CREATE OR REPLACE PACKAGE BODY ethiopian IS   FUNCTION is_even(item  IN INTEGER) RETURN BOOLEAN IS  BEGIN    RETURN item MOD 2 = 0;  END is_even;   FUNCTION double(item  IN INTEGER) RETURN INTEGER IS  BEGIN    RETURN item * 2;  END double;   FUNCTION half(item  IN INTEGER) RETURN INTEGER IS  BEGIN    RETURN TRUNC(item / 2);  END half;   FUNCTION multiply    ( left   IN INTEGER,      right  IN INTEGER)    RETURN INTEGER  IS    temp     INTEGER := 0;    plier    INTEGER := left;    plicand  INTEGER := right;  BEGIN     LOOP      IF NOT is_even(plier) THEN        temp := temp + plicand;      END IF;      EXIT WHEN plier <= 1;      plier := half(plier);      plicand := double(plicand);    END LOOP;     RETURN temp;   END multiply; END ethiopian;/ /* example call */BEGIN  DBMS_OUTPUT.put_line(ethiopian.multiply(17, 34));END;/

## Plain English

\All required helper routines already exist in Plain English:\\To cut a number in half:\Divide the number by 2.\\To double a number:\Add the number to the number.\\To decide if a number is odd:\Privatize the number.\Bitwise and the number with 1.\If the number is 0, say no.\Say yes. To run:Start up.Put 17 into a number.Multiply the number by 34 (Ethiopian).Convert the number to a string.Write the string to the console.Wait for the escape key.Shut down. To multiply a number by another number (Ethiopian):Put 0 into a sum number.Loop.If the number is 0, break.If the number is odd, add the other number to the sum.Cut the number in half.Double the other number.Repeat.Put the sum into the number.
Output:
578


## Powerbuilder

public function boolean wf_iseven (long al_arg);return mod(al_arg, 2 ) = 0end function public function long wf_halve (long al_arg);RETURN int(al_arg / 2)end function public function long wf_double (long al_arg);RETURN al_arg * 2end function public function long wf_ethiopianmultiplication (long al_multiplicand, long al_multiplier);// calculate resultlong ll_product DO WHILE al_multiplicand >= 1	IF wf_iseven(al_multiplicand) THEN		// do nothing	ELSE		ll_product += al_multiplier	END IF	al_multiplicand = wf_halve(al_multiplicand)	al_multiplier = wf_double(al_multiplier)LOOP return ll_productend function // example calllong ll_answerll_answer = wf_ethiopianmultiplication(17,34)

## PowerShell

function isEven {	param ([int]$value) return [bool]($value % 2 -eq 0)} function doubleValue {	param ([int]$value) return [int]($value * 2)} function halveValue {	param ([int]$value) return [int]($value / 2)} function multiplyValues {	param (		[int]$plier, [int]$plicand,		[int]$temp = 0 ) while ($plier -ge 1)	{		if (!(isEven $plier)) {$temp += $plicand }$plier = halveValue $plier$plicand = doubleValue $plicand } return$temp} multiplyValues 17 34

### Pipes with Busywork

This uses several PowerShell specific features, in functions everything is returned automatically, so explicitly stating return is unnecessary. type conversion happens automatically for certain types, [int] into [boolean] maps 0 to false and everything else to true. A hash is used to store the values as they are being written, then a pipeline is used to iterate over the keys of the hash, determine which are odd, and only sum those. The three-valued ForEach-Object is used to set a start expression, an iterative expression, and a return expression.

function halveInt( [int] $rhs ){ [math]::floor($rhs / 2 )} function doubleInt( [int] $rhs ){$rhs*2} function isEven( [int] $rhs ){ -not ($_ % 2 )} function Ethiopian( [int] $lhs , [int]$rhs ){	$scratch = @{} 1..[math]::floor( [math]::log($lhs , 2 ) + 1 ) | 	ForEach-Object { 		$scratch[$lhs] = $rhs$lhs		$lhs = halveInt($lhs )		$rhs = doubleInt($rhs ) } | 	Where-Object { -not ( isEven $_ ) } | ForEach-Object {$sum = 0 } { $sum +=$scratch[$_] } {$sum }} Ethiopian 17 34

## Prolog

halve(X,Y) :- Y is X // 2.double(X,Y) :- Y is 2*X.is_even(X) :- 0 is X mod 2. % columns(First,Second,Left,Right) is true if integers First and Second% expand into the columns Left and Right, respectivelycolumns(1,Second,[1],[Second]).columns(First,Second,[First|Left],[Second|Right]) :-    halve(First,Halved),    double(Second,Doubled),    columns(Halved,Doubled,Left,Right). % contribution(Left,Right,Amount) is true if integers Left and Right,% from their respective columns contribute Amount to the final sum.contribution(Left,_Right,0) :-    is_even(Left).contribution(Left,Right,Right) :-    \+ is_even(Left). ethiopian(First,Second,Product) :-    columns(First,Second,Left,Right),    maplist(contribution,Left,Right,Contributions),    sumlist(Contributions,Product).

### Functional Style

Using the same definitions as above for "halve/2", "double/2" and "is_even/2" along with an SWI-Prolog pack for function notation, one might write the following solution

:- use_module(library(func)). % halve/2, double/2, is_even/2 definitions go here ethiopian(First,Second,Product) :-    ethiopian(First,Second,0,Product). ethiopian(1,Second,Sum0,Sum) :-    Sum is Sum0 + Second.ethiopian(First,Second,Sum0,Sum) :-    Sum1 is Sum0 + Second*(First mod 2),    ethiopian(halve $First, double$ Second, Sum1, Sum).

### Constraint Handling Rules

This is a CHR solution for this problem using Prolog as the host language. Code will work in SWI-Prolog and YAP (and possibly in others with or without some minor tweaking).

:- module(ethiopia, [test/0, mul/3]). :- use_module(library(chr)). :- chr_constraint mul/3, halve/2, double/2, even/1, add_odd/4. mul(1, Y, S) <=>          S = Y.mul(X, Y, S) <=> X \= 1 | halve(X, X1),                          double(Y, Y1),                          mul(X1, Y1, S1),                          add_odd(X, Y, S1, S). halve(X, Y) <=> Y is X // 2. double(X, Y) <=> Y is X * 2. even(X) <=> 0 is X mod 2 | true.even(X) <=> 1 is X mod 2 | false. add_odd(X, _, A, S) <=> even(X)    | S is A.add_odd(X, Y, A, S) <=> \+ even(X) | S is A + Y. test :-    mul(17, 34, Z), !,    writeln(Z).
Note that the task statement is what makes the halve and double constraints required. Their use is highly artificial and a more realistic implementation would look like this:
:- module(ethiopia, [test/0, mul/3]). :- use_module(library(chr)). :- chr_constraint mul/3, even/1, add_if_odd/4. mul(1, Y, S) <=>          S = Y.mul(X, Y, S) <=> X \= 1 | X1 is X // 2,                          Y1 is Y * 2,                          mul(X1, Y1, S1),                          add_if_odd(X, Y, S1, S). even(X) <=> 0 is X mod 2 | true.even(X) <=> 1 is X mod 2 | false. add_if_odd(X, _, A, S) <=> even(X)    | S is A.add_if_odd(X, Y, A, S) <=> \+ even(X) | S is A + Y. test :-    mul(17, 34, Z),    writeln(Z).
Even this is more verbose than what a more native solution would look like.

## Python

### Python: With tutor

tutor = True def halve(x):    return x // 2 def double(x):    return x * 2 def even(x):    return not x % 2 def ethiopian(multiplier, multiplicand):    if tutor:        print("Ethiopian multiplication of %i and %i" %              (multiplier, multiplicand))    result = 0    while multiplier >= 1:        if even(multiplier):            if tutor:                print("%4i %6i STRUCK" %                      (multiplier, multiplicand))        else:            if tutor:                print("%4i %6i KEPT" %                      (multiplier, multiplicand))            result += multiplicand        multiplier   = halve(multiplier)        multiplicand = double(multiplicand)    if tutor:        print()    return result

Sample output

Python 3.1 (r31:73574, Jun 26 2009, 20:21:35) [MSC v.1500 32 bit (Intel)] on win32
>>> ethiopian(17, 34)
Ethiopian multiplication of 17 and 34
17     34 KEPT
8     68 STRUCK
4    136 STRUCK
2    272 STRUCK
1    544 KEPT

578
>>>

### Python: Without tutor

Without the tutorial code, and taking advantage of Python's lambda:

halve  = lambda x: x // 2double = lambda x: x*2even   = lambda x: not x % 2 def ethiopian(multiplier, multiplicand):    result = 0     while multiplier >= 1:        if not even(multiplier):            result += multiplicand        multiplier   = halve(multiplier)        multiplicand = double(multiplicand)     return result

### Python: With tutor. More Functional

Using some features which Python has for use in functional programming. The example also tries to show how to mix different programming styles while keeping close to the task specification, a kind of "executable pseudocode". Note: While column2 could theoretically generate a sequence of infinite length, izip will stop requesting values from it (and so provide the necessary stop condition) when column1 has no more values. When not using the tutor, table will generate the table on the fly in an efficient way, not keeping any intermediate values.
tutor = True from itertools import izip, takewhile def iterate(function, arg):    while 1:        yield arg        arg = function(arg) def halve(x): return x // 2def double(x): return x * 2def even(x): return x % 2 == 0 def show_heading(multiplier, multiplicand):    print "Multiplying %d by %d" % (multiplier, multiplicand),    print "using Ethiopian multiplication:"    print TABLE_FORMAT = "%8s %8s %8s %8s %8s" def show_table(table):    for p, q in table:        print TABLE_FORMAT % (p, q, "->",                              p, q if not even(p) else "-" * len(str(q))) def show_result(result):    print TABLE_FORMAT % ('', '', '', '', "=" * (len(str(result)) + 1))    print TABLE_FORMAT % ('', '', '', '', result) def ethiopian(multiplier, multiplicand):    def column1(x): return takewhile(lambda v: v >= 1, iterate(halve, x))    def column2(x): return iterate(double, x)    def rows(x, y): return izip(column1(x), column2(y))    table = rows(multiplier, multiplicand)    if tutor:         table = list(table)        show_heading(multiplier, multiplicand)        show_table(table)    result = sum(q for p, q in table if not even(p))    if tutor:         show_result(result)    return result
Example output:
>>> ethiopian(17, 34)
Multiplying 17 by 34 using Ethiopian multiplication:

     17       34       ->       17       34
8       68       ->        8       --
4      136       ->        4      ---
2      272       ->        2      ---
1      544       ->        1      544
====
578
578


### Python: as an unfold followed by a fold

Works with: Python version 3.7

Avoiding the use of the multiplication operator, and defining a catamorphism applied over an anamorphism.

'''Ethiopian multiplication''' from functools import reduce  # ethMult :: Int -> Int -> Intdef ethMult(n):    '''Ethiopian multiplication of n by m.'''     def doubled(x):        return x + x     def halved(h):        qr = divmod(h, 2)        if 0 < h:            print('halve:', str(qr).rjust(8, ' '))        return qr if 0 < h else None     def addedWhereOdd(a, remx):        odd, x = remx        if odd:            print(                str(a).rjust(2, ' '), '+',                str(x).rjust(3, ' '), '->',                str(a + x).rjust(3, ' ')            )            return a + x        else:            print(str(x).rjust(8, ' '))            return a     return lambda m: reduce(        addedWhereOdd,        zip(            unfoldr(halved)(n),            iterate(doubled)(m)        ),        0    )  # ------------------------- TEST -------------------------def main():    '''Tests of multiplication.'''     print(        '\nProduct:    ' + str(            ethMult(17)(34)        ),        '\n_______________\n'    )    print(        '\nProduct:    ' + str(            ethMult(34)(17)        )    )  # ----------------------- GENERIC ------------------------ # iterate :: (a -> a) -> a -> Gen [a]def iterate(f):    '''An infinite list of repeated       applications of f to x.    '''    def go(x):        v = x        while True:            yield v            v = f(v)    return go  # showLog :: a -> IO Stringdef showLog(*s):    '''Arguments printed with       intercalated arrows.'''    print(        ' -> '.join(map(str, s))    )  # unfoldr :: (b -> Maybe (a, b)) -> b -> [a]def unfoldr(f):    '''Dual to reduce or foldr.       Where catamorphism reduces a list to a summary value,       the anamorphic unfoldr builds a list from a seed value.       As long as f returns Just(a, b), a is prepended to the list,       and the residual b is used as the argument for the next       application of f.       When f returns Nothing, the completed list is returned.'''    def go(v):        xr = v, v        xs = []        while True:            xr = f(xr[0])            if xr:                xs.append(xr[1])            else:                return xs        return xs    return go  # MAIN ---if __name__ == '__main__':    main() 
Output:
halve:   (8, 1)
halve:   (4, 0)
halve:   (2, 0)
halve:   (1, 0)
halve:   (0, 1)
0 +  34 ->  34
68
136
272
34 + 544 -> 578

Product:    578
_______________

halve:  (17, 0)
halve:   (8, 1)
halve:   (4, 0)
halve:   (2, 0)
halve:   (1, 0)
halve:   (0, 1)
17
0 +  34 ->  34
68
136
272
34 + 544 -> 578

Product:    578

## Quackery

Translation of: Forth

Extended to handle negative numbers.

[ 1 & not ]                is even   (   n --> b ) [ 1 << ]                   is double (   n --> n ) [ 1 >> ]                   is halve  (   n --> n ) [ dup 0 < unrot abs  [ dup 0 = iff nip done    over double over halve    recurse    swap even    iff nip else + ]  swap if negate ]         is e*     ( n n --> n )

## R

### R: With tutor

halve <- function(a) floor(a/2)double <- function(a) a*2iseven <- function(a) (a%%2)==0 ethiopicmult <- function(plier, plicand, tutor=FALSE) {  if (tutor) { cat("ethiopic multiplication of", plier, "and", plicand, "\n") }  result <- 0  while(plier >= 1) {    if (!iseven(plier)) { result <- result + plicand }    if (tutor) {      cat(plier, ", ", plicand, " ", ifelse(iseven(plier), "struck", "kept"), "\n", sep="")    }    plier <- halve(plier)    plicand <- double(plicand)  }  result} print(ethiopicmult(17, 34, TRUE))

### R: Without tutor

Simplified version.

 halve <- function(a) floor(a/2)double <- function(a) a*2iseven <- function(a) (a%%2)==0 ethiopicmult<-function(x,y){	res<-ifelse(iseven(y),0,x)	while(!y==1){		x<-double(x)		y<-halve(y)		if(!iseven(y)) res<-res+x	}	return(res)} print(ethiopicmult(17,34)) 

## Racket

#lang racket (define (halve  i) (quotient i 2))(define (double i) (* i 2));; even?' is built-in (define (ethiopian-multiply x y)  (cond [(zero? x) 0]        [(even? x) (ethiopian-multiply (halve x) (double y))]        [else (+ y (ethiopian-multiply (halve x) (double y)))])) (ethiopian-multiply 17 34) ; -> 578

## Raku

(formerly Perl 6)

sub halve  (Int $n is rw) {$n div= 2 }sub double (Int $n is rw) {$n *= 2 }sub even   (Int $n --> Bool) {$n %% 2 } sub ethiopic-mult (Int $a is copy, Int$b is copy --> Int) {    my Int $r = 0; while$a {	even $a or$r += $b; halve$a;	double $b; } return$r;} say ethiopic-mult(17,34);
Output:
578


More succinctly using implicit typing, primed lambdas, and an infinite loop:

sub ethiopic-mult {    my &halve  = * div= 2;    my &double = * *= 2;    my &even   = * %% 2;     my ($a,$b) = @_;    my $r; loop { even$a or $r +=$b;        halve $a or return$r;        double $b; }} say ethiopic-mult(17,34); More succinctly still, using a pure functional approach (reductions, mappings, lazy infinite sequences): sub halve {$^n div 2 }sub double { $^n * 2 }sub even {$^n %% 2  } sub ethiopic-mult ($a,$b) {    [+] ($b, &double ... *) Z* ($a, &halve ... 0).map: { not even $^n }} say ethiopic-mult(17,34); (same output) ## Rascal import IO; public int halve(int n) = n/2; public int double(int n) = n*2; public bool uneven(int n) = (n % 2) != 0); public int ethiopianMul(int n, int m) { result = 0; while(n >= 1) { if(uneven(n)) result += m; n = halve(n); m = double(m); } return result;}  ## Red Red["Ethiopian multiplication"] halve: function [n][n >> 1]double: function [n][n << 1];== even? already exists ethiopian-multiply: function [ "Returns the product of two integers using Ethiopian multiplication" a [integer!] "The multiplicand" b [integer!] "The multiplier"][ result: 0 while [a <> 0][ if odd? a [result: result + b] a: halve a b: double b ] result] print ethiopian-multiply 17 34 Output: 578  ## Relation  function half(x)set result = floor(x/2)end function function double(x)set result = 2*xend function function even(x)set result = (x/2 > floor(x/2))end function program ethiopian_mul(a,b)relation first, secondwhile a >= 1insert a, bset a = half(a)set b = double(b)end whileextend third = even(first) * secondproject third sumend program run ethiopian_mul(17,34)print  ## REXX These two REXX versions properly handle negative integers. ### sans error checking /*REXX program multiplies two integers by the Ethiopian (or Russian peasant) method. */numeric digits 3000 /*handle some gihugeic integers. */parse arg a b . /*get two numbers from the command line*/say 'a=' a /*display a formatted value of A. */say 'b=' b /* " " " " " B. */say 'product=' eMult(a, b) /*invoke eMult & multiple two integers.*/exit /*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/eMult: procedure; parse arg x,y; s=sign(x) /*obtain the two arguments; sign for X.*/$=0                                     /*product of the two integers (so far).*/                      do  while x\==0            /*keep processing while   X   not zero.*/                      if \isEven(x)  then $=$+y  /*if odd,  then add   Y   to product.  */                      x= halve(x)                /*invoke the  HALVE   function.        */                      y=double(y)                /*   "    "   DOUBLE      "            */                      end   /*while*/            /* [↑]  Ethiopian multiplication method*/         return *s/1 /*maintain the correct sign for product*//*──────────────────────────────────────────────────────────────────────────────────────*/double: return arg(1) * 2 /* * is REXX's multiplication. */halve: return arg(1) % 2 /* % " " integer division. */isEven: return arg(1) // 2 == 0 /* // " " division remainder.*/ output when the following input is used: 30 -7 a= 30 b= -7 product= -210  ### with error checking This REXX version also aligns the "input" messages and also performs some basic error checking. Note that the 2nd number needn't be an integer, any valid number will work. /*REXX program multiplies two integers by the Ethiopian (or Russian peasant) method. */numeric digits 3000 /*handle some gihugeic integers. */parse arg a b _ . /*get two numbers from the command line*/if a=='' then call error "1st argument wasn't specified."if b=='' then call error "2nd argument wasn't specified."if _\=='' then call error "too many arguments were specified: " _if \datatype(a, 'W') then call error "1st argument isn't an integer: " aif \datatype(b, 'N') then call error "2nd argument isn't a valid number: " bp=eMult(a, b) /*Ethiopian or Russian peasant method. */w=max(length(a), length(b), length(p)) /*find the maximum width of 3 numbers. */say ' a=' right(a, w) /*use right justification to display A.*/say ' b=' right(b, w) /* " " " " " B.*/say 'product=' right(p, w) /* " " " " " P.*/exit /*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/eMult: procedure; parse arg x,y; s=sign(x) /*obtain the two arguments; sign for X.*/=0                                     /*product of the two integers (so far).*/                      do  while x\==0            /*keep processing while   X   not zero.*/                      if \isEven(x)  then $=$+y  /*if odd,  then add   Y   to product.  */                      x= halve(x)                /*invoke the  HALVE   function.        */                      y=double(y)                /*   "    "   DOUBLE      "            */                      end   /*while*/            /* [↑]  Ethiopian multiplication method*/         return $*s/1 /*maintain the correct sign for product*//*──────────────────────────────────────────────────────────────────────────────────────*/double: return arg(1) * 2 /* * is REXX's multiplication. */halve: return arg(1) % 2 /* % " " integer division. */isEven: return arg(1) // 2 == 0 /* // " " division remainder.*/error: say '***error!***' arg(1); exit 13 /*display an error message to terminal.*/ output when the following input is used: 200 0.333  a= 200 b= 0.333 product= 66.6  ## Ring  x = 17y = 34p = 0while x != 0 if not even(x) p += y see "" + x + " " + " " + y + nl else see "" + x + " ---" + nl ok x = halve(x) y = double(y)endsee " " + " ===" + nl see " " + p func double n return (n * 2) func halve n return floor(n / 2)func even n return ((n & 1) = 0)  Output: 17 34 8 --- 4 --- 2 --- 1 544 === 578  ## Ruby Iterative and recursive implementations here. I've chosen to highlight the example 20*5 which I think is more illustrative. def halve(x) x/2 enddef double(x) x*2 end # iterativedef ethiopian_multiply(a, b) product = 0 while a >= 1 p [a, b, a.even? ? "STRIKE" : "KEEP"] if$DEBUG    product += b unless a.even?    a = halve(a)    b = double(b)  end  productend # recursivedef rec_ethiopian_multiply(a, b)  return 0 if a < 1  p [a, b, a.even? ? "STRIKE" : "KEEP"] if $DEBUG (a.even? ? 0 : b) + rec_ethiopian_multiply(halve(a), double(b))end$DEBUG = true   # $DEBUG also set to true if "-d" option givena, b = 20, 5puts "#{a} * #{b} = #{ethiopian_multiply(a,b)}"; puts Output: [20, 5, "STRIKE"] [10, 10, "STRIKE"] [5, 20, "KEEP"] [2, 40, "STRIKE"] [1, 80, "KEEP"] 20 * 5 = 100 A test suite: require 'test/unit'class EthiopianTests < Test::Unit::TestCase def test_iter1; assert_equal(578, ethopian_multiply(17,34)); end def test_iter2; assert_equal(100, ethopian_multiply(20,5)); end def test_iter3; assert_equal(5, ethopian_multiply(5,1)); end def test_iter4; assert_equal(5, ethopian_multiply(1,5)); end def test_iter5; assert_equal(0, ethopian_multiply(5,0)); end def test_iter6; assert_equal(0, ethopian_multiply(0,5)); end def test_rec1; assert_equal(578, rec_ethopian_multiply(17,34)); end def test_rec2; assert_equal(100, rec_ethopian_multiply(20,5)); end def test_rec3; assert_equal(5, rec_ethopian_multiply(5,1)); end def test_rec4; assert_equal(5, rec_ethopian_multiply(1,5)); end def test_rec5; assert_equal(0, rec_ethopian_multiply(5,0)); end def test_rec6; assert_equal(0, rec_ethopian_multiply(0,5)); endend Run options: # Running tests: ............ Finished tests in 0.014001s, 857.0816 tests/s, 857.0816 assertions/s. 12 tests, 12 assertions, 0 failures, 0 errors, 0 skips ruby -v: ruby 2.0.0p247 (2013-06-27) [i386-mingw32]  ## Rust fn double(a: i32) -> i32 { 2*a} fn halve(a: i32) -> i32 { a/2} fn is_even(a: i32) -> bool { a % 2 == 0} fn ethiopian_multiplication(mut x: i32, mut y: i32) -> i32 { let mut sum = 0; while x >= 1 { print!("{} \t {}", x, y); match is_even(x) { true => println!("\t Not Kept"), false => { println!("\t Kept"); sum += y; } } x = halve(x); y = double(y); } sum} fn main() { let output = ethiopian_multiplication(17, 34); println!("---------------------------------"); println!("\t {}", output);} Output: 17 34 Kept 8 68 Not Kept 4 136 Not Kept 2 272 Not Kept 1 544 Kept --------------------------------- 578 ## S-BASIC $constant true  =  0FFFFH$constant false = 0 function half(n = integer) = integerend = n / 2 function twice(n = integer) = integerend = n + n rem - return true (-1) if n is even, otherwise false function even(n = integer) = integervar one = integer one = 1 rem - only variables are compared bitwiseend = ((n and one) = 0) rem - return i * j, optionally showing stepsfunction ethiopian(i, j, show = integer) = integer var p = integer p = 0 while i >= 1 do begin if even(i) then begin if show then print i;" ---";j end else begin if show then print i;" ";j;"+" p = p + j end i = half(i) j = twice(j) end if show then begin print "----------" print " ="; endend = p rem - exercise the functionprint "Multiplying 17 times 34"print ethiopian(17,34,true) end Output: Multiplying 17 times 34 17 34+ 8 --- 68 4 --- 136 2 --- 272 1 544+ ---------- = 578 ## Scala The first and second are only slightly different and use functional style. The third uses a for loop to yield the result. The fourth uses recursion.  def ethiopian(i:Int, j:Int):Int= pairIterator(i,j).filter(x=> !isEven(x._1)).map(x=>x._2).foldLeft(0){(x,y)=>x+y} def ethiopian2(i:Int, j:Int):Int= pairIterator(i,j).map(x=>if(isEven(x._1)) 0 else x._2).foldLeft(0){(x,y)=>x+y} def ethiopian3(i:Int, j:Int):Int={ var res=0; for((h,d) <- pairIterator(i,j) if !isEven(h)) res+=d; res} def ethiopian4(i: Int, j: Int): Int = if (i == 1) j else ethiopian(halve(i), double(j)) + (if (isEven(i)) 0 else j) def isEven(x:Int)=(x&1)==0def halve(x:Int)=x>>>1def double(x:Int)=x<<1 // generates pairs of values (halve,double)def pairIterator(x:Int, y:Int)=new Iterator[(Int, Int)]{ var i=(x, y) def hasNext=i._1>0 def next={val r=i; i=(halve(i._1), double(i._2)); r}}  ## Scheme In Scheme, even? is a standard procedure. (define (halve num) (quotient num 2)) (define (double num) (* num 2)) (define (*mul-eth plier plicand acc) (cond ((zero? plier) acc) ((even? plier) (*mul-eth (halve plier) (double plicand) acc)) (else (*mul-eth (halve plier) (double plicand) (+ acc plicand))))) (define (mul-eth plier plicand) (*mul-eth plier plicand 0)) (display (mul-eth 17 34))(newline) Output: 578  ## Seed7 Ethiopian Multiplication is another name for the peasant multiplication: const proc: double (inout integer: a) is func begin a *:= 2; end func; const proc: halve (inout integer: a) is func begin a := a div 2; end func; const func boolean: even (in integer: a) is return not odd(a); const func integer: peasantMult (in var integer: a, in var integer: b) is func result var integer: result is 0; begin while a <> 0 do if not even(a) then result +:= b; end if; halve(a); double(b); end while; end func; Original source (without separate functions for doubling, halving, and checking if a number is even): [2] ## Sidef func double (n) { n << 1 }func halve (n) { n >> 1 }func isEven (n) { n&1 == 0 } func ethiopian_mult(a, b) { var r = 0 while (a > 0) { r += b if !isEven(a) a = halve(a) b = double(b) } return r} say ethiopian_mult(17, 34) Output: 578  ## Smalltalk Works with: GNU Smalltalk Number extend [ double [ ^ self * 2 ] halve [ ^ self // 2 ] ethiopianMultiplyBy: aNumber withTutor: tutor [ |result multiplier multiplicand| multiplier := self. multiplicand := aNumber. tutor ifTrue: [ ('ethiopian multiplication of %1 and %2' % { multiplier. multiplicand }) displayNl ]. result := 0. [ multiplier >= 1 ] whileTrue: [ multiplier even ifFalse: [ result := result + multiplicand. tutor ifTrue: [ ('%1, %2 kept' % { multiplier. multiplicand }) displayNl ] ] ifTrue: [ tutor ifTrue: [ ('%1, %2 struck' % { multiplier. multiplicand }) displayNl ] ]. multiplier := multiplier halve. multiplicand := multiplicand double. ]. ^result ] ethiopianMultiplyBy: aNumber [ ^ self ethiopianMultiplyBy: aNumber withTutor: false ]]. (17 ethiopianMultiplyBy: 34 withTutor: true) displayNl. ## SNOBOL4  define('halve(num)') :(halve_end)halve eq(num,1) :s(freturn) halve = num / 2 :(return)halve_end define('double(num)') :(double_end)double double = num * 2 :(return)double_end define('odd(num)') :(odd_end)odd eq(num,1) :s(return) eq(num,double(halve(num))) :s(freturn)f(return) odd_end l = trim(input) r = trim(input) s = 0next s = odd(l) s + r r = double(r) l = halve(l) :s(next)stop output = send ## SNUSP  /==!/[email protected]@@[email protected]# | | /-\ /recurse\ #/?\ zero$>,@/>,@/?\<=zero=!\?/<=print==!\@\>?!\@/<@\.!\-/        < @     #                 |   \=/  \[email protected]@@[email protected]+++++#     /==\ \===?!/===-?\>>+# halve !     /+ !/+ !/+ !/+   \    mod10#    !  @ |  #>>\?-<+>/           /<+> -\!?-\!?-\!?-\!?-\!/-<+>\  > ?     />+<<++>-\        \?!\-?!\-?!\-?!\-?!\-?/\    div10?down?  | \-<<<!\=======?/\ add &    #  +/! +/! +/! +/! +/\>+<-/  | \=<<<!/====?\=\ | double!    #  |       \<++>-/ | |\=======\[email protected]>============/!/

This is possibly the smallest multiply routine so far discovered for SNUSP.

## Soar

########################################### multiply takes ^left and ^right numbers# and a ^return-tosp {multiply*elaborate*initialize   (state <s> ^superstate.operator <o>)   (<o> ^name multiply        ^left <x>        ^right <y>        ^return-to <r>)-->   (<s> ^name multiply        ^left <x>        ^right <y>        ^return-to <r>)} sp {multiply*propose*recurse   (state <s> ^name multiply              ^left <x> > 0              ^right <y>              ^return-to <r>             -^multiply-done)-->   (<s> ^operator <o> +)   (<o> ^name multiply        ^left (div <x> 2)        ^right (* <y> 2)        ^return-to <s>)} sp {multiply*elaborate*mod   (state <s> ^name multiply              ^left <x>)-->   (<s> ^left-mod-2 (mod <x> 2))} sp {multiply*elaborate*recursion-done-even   (state <s> ^name multiply              ^left <x>              ^right <y>              ^multiply-done <temp>              ^left-mod-2 0)-->   (<s> ^answer <temp>)} sp {multiply*elaborate*recursion-done-odd   (state <s> ^name multiply              ^left <x>              ^right <y>              ^multiply-done <temp>              ^left-mod-2 1)-->   (<s> ^answer (+ <temp> <y>))} sp {multiply*elaborate*zero   (state <s> ^name multiply              ^left 0)-->   (<s> ^answer 0)} sp {multiply*elaborate*done   (state <s> ^name multiply              ^return-to <r>              ^answer <a>)-->   (<r> ^multiply-done <a>)}

## Swift

import Darwin func ethiopian(var #int1:Int, var #int2:Int) -> Int {  var lhs = [int1], rhs = [int2]   func isEven(#n:Int) -> Bool {return n % 2 == 0}  func double(#n:Int) -> Int {return n * 2}  func halve(#n:Int) -> Int {return n / 2}   while int1 != 1 {    lhs.append(halve(n: int1))    rhs.append(double(n: int2))    int1 = halve(n: int1)    int2 = double(n: int2)  }   var returnInt = 0  for (a,b) in zip(lhs, rhs) {    if (!isEven(n: a)) {      returnInt += b    }  }  return returnInt} println(ethiopian(int1: 17, int2: 34))
Output:
578

## Tcl

# This is how to declare functions - the mathematical entities - as opposed to proceduresproc function {name arguments body} {    uplevel 1 [list proc tcl::mathfunc::$name$arguments [list expr $body]]} function double n {$n * 2}function halve n {$n / 2}function even n {($n & 1) == 0}function mult {a b} {    $a < 1 ? 0 : even($a) ? [logmult STRUCK] + mult(halve($a), double($b))	     : [logmult KEPT]   + mult(halve($a), double($b)) + $b} # Wrapper to set up the loggingproc ethiopianMultiply {a b {tutor false}} { if {$tutor} {	set wa [expr {[string length $a]+1}] set wb [expr {$wa+[string length $b]-1}] puts stderr "Ethiopian multiplication of$a and $b" interp alias {} logmult {} apply {{wa wb msg} { upvar 1 a a b b puts stderr [format "%*d %*d %s"$wa $a$wb $b$msg]	    return 0	}} $wa$wb    } else {	proc logmult args {return 0}    }    return [expr {mult($a,$b)}]}
Demo code:
puts "17 * 34 = [ethiopianMultiply 17 34 true]"
Output:
Ethiopian multiplication of 17 and 34
17   34 KEPT
8   68 STRUCK
4  136 STRUCK
2  272 STRUCK
1  544 KEPT
17 * 34 = 578


## TUSCRIPT

  MODE TUSCRIPTASK "insert number1", nr1=""ASK "insert number2", nr2="" SET nrs=APPEND(nr1,nr2),size_nrs=SIZE(nrs)IF (size_nrs!=2) ERROR/STOP "insert two numbers"LOOP n=nrsIF (n!='digits') ERROR/STOP n, " is not a digit"ENDLOOP PRINT "ethopian multiplication of ",nr1," and ",nr2 SET sum=0SECTION checkifevenSET even=MOD(nr1,2) IF (even==0) THEN   SET action="struck" ELSE   SET action="kept"   SET sum=APPEND (sum,nr2) ENDIFSET nr1=CENTER (nr1,+6),nr2=CENTER (nr2,+6),action=CENTER (action,8)PRINT nr1,nr2,actionENDSECTION SECTION halve_iSET nr1=nr1/2ENDSECTION SECTION double_inr2=nr2*2ENDSECTION DO checkifeven LOOPDO halve_iDO double_iDO checkifevenIF (nr1==1) EXITENDLOOP SET line=REPEAT ("=",20), sum = sum(sum),sum=CENTER (sum,+12)PRINT linePRINT sum
Output:
ethopian multiplication of 17 and 34
17    34  kept
8    68 struck
4   136 struck
2   272 struck
1   544  kept
====================
578


## UNIX Shell

Tried with bash --posix, and also with Heirloom's sh. Beware that bash --posix has more features than sh; this script uses only sh features.

Works with: Bourne Shell
halve(){    expr "$1" / 2} double(){ expr "$1" \* 2} is_even(){    expr "$1" % 2 = 0 >/dev/null} ethiopicmult(){ plier=$1    plicand=$2 r=0 while [ "$plier" -ge 1 ]; do	is_even "$plier" || r=expr$r + "$plicand" plier=halve "$plier"	plicand=double "$plicand" done echo$r} ethiopicmult 17 34# => 578

While breaking if the --posix flag is passed to bash, the following alternative script avoids the *, /, and % operators. It also uses local variables and built-in arithmetic.

Works with: bash
Works with: pdksh
Works with: zsh
halve() {  (( $1 >>= 1 ))} double() { (($1 <<= 1 ))} is_even() {  (( ($1 & 1) == 0 ))} multiply() { local plier=$1  local plicand=$2 local result=0 while (( plier > 0 )) do is_even plier || (( result += plicand )) halve plier double plicand done echo$result} multiply 17 34# => 578

### C Shell

alias halve '@ \!:1 /= 2'alias double '@ \!:1 *= 2'alias is_even '@ \!:1 = ! ( \!:2 % 2 )' alias multiply eval \''set multiply_args=( \!*:q )		\\	@ multiply_plier = $multiply_args[2] \\ @ multiply_plicand =$multiply_args[3]			\\	@ multiply_result = 0					\\	while ( $multiply_plier > 0 ) \\ is_even multiply_is_even$multiply_plier	\\		if ( ! $multiply_is_even ) then \\ @ multiply_result +=$multiply_plicand	\\		endif						\\		halve multiply_plier				\\		double multiply_plicand				\\	end							\\	@ $multiply_args[1] =$multiply_result			\\'\' multiply p 17 34echo \$p# => 578

## Ursala

This solution makes use of the functions odd, double, and half, which respectively check the parity, double a given natural number, or perform truncating division by two. These functions are normally imported from the nat library but defined here explicitly for

the sake of completeness.
odd    = ~&ihBdouble = ~&iNiCBhalf   = ~&itB
The functions above are defined in terms of bit manipulations exploiting the concrete representations of natural numbers. The remaining code treats natural numbers instead as abstract types by way of the library API, and uses the operators for distribution (*-), triangular iteration (|\), and filtering (*~) among others.
#import nat emul = sum:[email protected]+ [email protected]*~+ ^|(~&,double)|\+ *-^|\~& @iNC ~&h~=0->tx :^/[email protected] ~&
test program:
#cast %n test = emul(34,17)
Output:
578


## VBA

Define three named functions :

1. one to halve an integer,
2. one to double an integer, and
3. one to state if an integer is even.
Private Function lngHalve(Nb As Long) As Long    lngHalve = Nb / 2End Function Private Function lngDouble(Nb As Long) As Long    lngDouble = Nb * 2End Function Private Function IsEven(Nb As Long) As Boolean    IsEven = (Nb Mod 2 = 0)End Function

Use these functions to create a function that does Ethiopian multiplication. The first function below is a non optimized function :

Private Function Ethiopian_Multiplication_Non_Optimized(First As Long, Second As Long) As LongDim Left_Hand_Column As New Collection, Right_Hand_Column As New Collection, i As Long, temp As Long 'Take two numbers to be multiplied and write them down at the top of two columns.    Left_Hand_Column.Add First, CStr(First)    Right_Hand_Column.Add Second, CStr(Second)'In the left-hand column repeatedly halve the last number, discarding any remainders,    'and write the result below the last in the same column, until you write a value of 1.    Do        First = lngHalve(First)        Left_Hand_Column.Add First, CStr(First)    Loop While First > 1'In the right-hand column repeatedly double the last number and write the result below.    'stop when you add a result in the same row as where the left hand column shows 1.    For i = 2 To Left_Hand_Column.Count        Second = lngDouble(Second)        Right_Hand_Column.Add Second, CStr(Second)    Next 'Examine the table produced and discard any row where the value in the left column is even.    For i = Left_Hand_Column.Count To 1 Step -1        If IsEven(Left_Hand_Column(i)) Then Right_Hand_Column.Remove CStr(Right_Hand_Column(i))    Next'Sum the values in the right-hand column that remain to produce the result of multiplying    'the original two numbers together    For i = 1 To Right_Hand_Column.Count        temp = temp + Right_Hand_Column(i)    Next    Ethiopian_Multiplication_Non_Optimized = tempEnd Function

This one is better :

Private Function Ethiopian_Multiplication(First As Long, Second As Long) As Long    Do        If Not IsEven(First) Then Mult_Eth = Mult_Eth + Second        First = lngHalve(First)        Second = lngDouble(Second)    Loop While First >= 1    Ethiopian_Multiplication = Mult_Eth End Function

Then you can call one of these functions like this :

Sub Main_Ethiopian()Dim result As Long    result = Ethiopian_Multiplication(17, 34)    ' or :    'result = Ethiopian_Multiplication_Non_Optimized(17, 34)    Debug.Print resultEnd Sub

## VBScript

Nowhere near as optimal a solution as the Ada. Yes, it could have made as optimal, but the long way seemed more interesting.

Demonstrates a List class. The .recall and .replace methods have bounds checking but the code does not test for the exception that would be raised. List class extends the storage allocated for the list when the occupation of the list goes beyond the original allocation.

option explicit makes sure that all variables are declared.

Implementation
option explicit class List	private theList	private nOccupiable	private nTop 	sub class_initialize		nTop = 0		nOccupiable = 100		redim theList( nOccupiable )	end sub 	public sub store( x )		if nTop >= nOccupiable then			nOccupiable = nOccupiable + 100			redim preserve theList( nOccupiable )		end if		theList( nTop ) = x		nTop = nTop + 1	end sub 	public function recall( n )		if n >= 0 and n <= nOccupiable then			recall = theList( n )		else			err.raise vbObjectError + 1000,,"Recall bounds error"		end if	end function 	public sub replace( n, x )		if n >= 0 and n <= nOccupiable then			theList( n )  = x		else			err.raise vbObjectError + 1001,,"Replace bounds error"		end if	end sub 	public property get listCount		listCount = nTop	end property end class function halve( n )	halve = int( n / 2 )end function function twice( n )	twice = int( n * 2 )end function function iseven( n )	iseven = ( ( n mod 2 ) = 0 )end function  function multiply( n1, n2 )	dim LL	set LL = new List 	dim RR	set RR = new List 	LL.store n1	RR.store n2 	do while n1 <> 1		n1 = halve( n1 )		LL.store n1		n2 = twice( n2 )		RR.store n2	loop 	dim i	for i = 0 to LL.listCount		if iseven( LL.recall( i ) ) then			RR.replace i, 0		end if	next 	dim total	total = 0	for i = 0 to RR.listCount		total = total + RR.recall( i )	next 	multiply = totalend function
Invocation
 wscript.echo multiply(17,34)
Output:
578


## Wren

var halve = Fn.new { |n| (n/2).truncate } var double = Fn.new { |n| n * 2 } var isEven = Fn.new { |n| n%2 == 0 } var ethiopian = Fn.new { |x, y|    var sum = 0    while (x >= 1) {        if (!isEven.call(x)) sum = sum + y        x = halve.call(x)        y = double.call(y)    }    return sum} System.print("17 x 34 = %(ethiopian.call(17, 34))")System.print("99 x 99 = %(ethiopian.call(99, 99))")
Output:
17 x 34 = 578
99 x 99 = 9801


## x86 Assembly

Works with: nasm
, linking with the C standard library and start code.
	extern 	printf	global	main 	section	.text halve	shr	ebx, 1	ret double	shl	ebx, 1	ret iseven	and	ebx, 1	cmp	ebx, 0	ret			; ret preserves flags main	push	1		; tutor = true	push	34		; 2nd operand	push	17		; 1st operand	call	ethiopicmult	add	esp, 12 	push	eax		; result of 17*34	push	fmt	call	printf	add	esp, 8 	ret  %define plier 8%define plicand 12%define tutor 16 ethiopicmult	enter	0, 0	cmp	dword [ebp + tutor], 0	je	.notut0	push	dword [ebp + plicand]	push	dword [ebp + plier]	push	preamblefmt	call	printf	add	esp, 12.notut0 	xor	eax, eax		; eax -> result	mov	ecx, [ebp + plier] 	; ecx -> plier	mov	edx, [ebp + plicand]    ; edx -> plicand .whileloop	cmp	ecx, 1	jl	.multend	cmp	dword [ebp + tutor], 0	je	.notut1	call	tutorme.notut1	mov	ebx, ecx	call	iseven	je	.iseven	add	eax, edx	; result += plicand.iseven	mov	ebx, ecx	; plier >>= 1	call	halve	mov	ecx, ebx 	mov	ebx, edx	; plicand <<= 1	call	double	mov	edx, ebx 	jmp	.whileloop.multend	leave	ret  tutorme	push	eax	push	strucktxt	mov	ebx, ecx	call	iseven	je	.nostruck	mov	dword [esp], kepttxt.nostruck	push	edx	push	ecx	push	tutorfmt	call	printf	add	esp, 4	pop	ecx	pop	edx	add	esp, 4	pop	eax	ret 	section .data fmt	db	"%d", 10, 0preamblefmt	db	"ethiopic multiplication of %d and %d", 10, 0tutorfmt	db	"%4d %6d %s", 10, 0strucktxt	db	"struck", 0kepttxt	db	"kept", 0

### Smaller version

Using old style 16 bit registers created in debug

The functions to halve double and even are coded inline. To half a value

  shr,1


to double a value

  shl,1


to test if the value is even

test,01jz   EvenOdd:Even:
;calling program  1BDC:0100 6A11           PUSH   11  ;17  Put operands on the stack 1BDC:0102 6A22           PUSH   22  ;34 1BDC:0104 E80900         CALL   0110  ; call the mulitplcation routine;putting some space in, (not needed) 1BDC:0107 90             NOP 1BDC:0108 90             NOP 1BDC:0109 90             NOP 1BDC:010A 90             NOP 1BDC:010B 90             NOP 1BDC:010C 90             NOP 1BDC:010D 90             NOP 1BDC:010E 90             NOP 1BDC:010F 90             NOP;mulitplication routine starts here 1BDC:0110 89E5           MOV    BP,SP      ; prepare to get operands off stack 1BDC:0112 8B4E02         MOV    CX,[BP+02] ; Get the first operand 1BDC:0115 8B5E04         MOV    BX,[BP+04] ; get the second oerand 1BDC:0118 31C0           XOR    AX,AX      ; zero out the result 1BDC:011A F7C10100       TEST   CX,0001     ; are we odd 1BDC:011E 7402           JZ     0122       ; no skip the next instruction 1BDC:0120 01D8           ADD    AX,BX     ; we are odd so add to the result 1BDC:0122 D1E3           SHL    BX,1      ; multiply by 2 1BDC:0124 D1E9           SHR    CX,1      ; divide by 2 (if zr flag is set, we are done) 1BDC:0126 75F2           JNZ    011A      ; cx not 0, go back and do it again 1BDC:0128 C3             RET              ; return with the result in AX ;pretty small, just 24 bytes

## XPL0

include c:\cxpl\codes;  \intrinsic 'code' declarations func Halve(N);          \Return half of Nint  N;return N>>1; func Double(N);         \Return N doubledint  N;return N<<1; func IsEven(N);         \Return 'true' if N is an even numberint  N;return (N&1)=0; func EthiopianMul(A, B); \Multiply A times B using Ethiopian methodint  A, B;int  I, J, S, Left(100), Right(100);[Left(0):= A;  Right(0):= B;            \1. write numbers to be multipliedI:= 1;                                  \2. repeatedly halve number on leftrepeat  A:= Halve(A);        Left(I):= A;  I:= I+1;until   A=1;J:= 1;                                  \3. repeatedly double number on rightrepeat  B:= Double(B);        Right(J):= B;  J:= J+1;until   J=I;                            \stop where left column = 1for J:= 0 to I-1 do                     \4. discard right value if left is even        if IsEven(Left(J)) then Right(J):= 0;S:= 0;                                  \5. sum remaining values on rightfor J:= 0 to I-1 do        S:= S + Right(J);for J:= 0 to I-1 do                     \show this insanity        [IntOut(0, Left(J));  ChOut(0, 9\tab\);  IntOut(0, Right(J));  CrLf(0)];Text(0, "       --------");return S;                               \sum = product]; int Product;[Product:= EthiopianMul(17, 34);ChOut(0, 9);  IntOut(0, Product);  CrLf(0);  CrLf(0);Product:= EthiopianMul(1234, 5678);ChOut(0, 9);  IntOut(0, Product);  CrLf(0);]
Output:
17      34
8       0
4       0
2       0
1       544
--------
578

1234    0
617     11356
308     0
154     0
77      90848
38      0
19      363392
9       726784
4       0
2       0
1       5814272
--------
7006652

## zkl

Trying to duplicate the task as stated, using columns. isEven is a integer method.

fcn ethiopianMultiply(l,r){ // l is a non-negative integer   halve  :=fcn(n){ n/2 };   double :=fcn(n){ n+n };   lr:=List(T(l,r)); // ( (l,r) .. (1,r*n) )   while(l>1){ lr.write( T(l=halve(l),r=double(r)) ) }   lr.filter(fcn([(l,r)]){ (not l.isEven) }); // strike out even left rows   .reduce(fcn(sum,[(l,r)]){ sum + r },0);  // sum right column}
foreach l,r in ( T(T(17,34),T(34,1),T(34,2),T(34,0)) ){   println(ethiopianMultiply(l,r)," ",ethiopianMultiply(r,l));}
Output:
578 578
34 34
68 68
0 0


## Z80 Assembly

	org &8000 	ld hl,17	call Halve_Until_1 	push bc	ld hl,34	call Double_Until_1	pop bc 	call SumOddEntries	;returns Ethiopian product in IX. 	call NewLine 	call Primm	byte "0x",0 	push ix	pop hl 	ld a,H	call ShowHex		;Output should be in decimal but hex is easier.	ld a,L	call ShowHex 	ret  Halve_Until_1:	;input: HL = number you wish to halve. HL is unsigned.	ld de,Column_1	ld a,1	ld (Column_1),HL	inc de	inc deloop_HalveUntil_1:	SRL H	RR L	inc b	push af		ld a,L		ld (de),a		inc de		ld a,H		ld (de),a		inc de	pop af	CP L	jr nz,loop_HalveUntil_1	;b tracks how many times to double the second factor.	ret Double_Until_1:	;doubles second factor B times. B is calculated by Halve_until_1	ld de,Column_2	ld (Column_2),HL	inc de	inc deloop_double_until_1:	SLA L	RL H	PUSH AF		LD A,L		LD (DE),A		INC DE		LD A,H		LD (DE),A		INC DE	POP AF	DJNZ loop_double_until_1	ret  SumOddEntries:	sla b			;double loop counter, this is also the offset to the "last" entry of					;each table	ld h,>Column_1	ld d,>Column_2	;aligning the tables lets us get away with this.	ld l,b	ld e,b	ld ix,0loop:	ld a,(hl)	rrca	;we only need the result of the odd/even test.	jr nc,skipEven	push hl	push de		ld a,(de)		ld L,a		inc de		ld a,(de)		ld H,a		ex de,hl		add ix,de	pop de	pop hlskipEven:	dec de	dec de	dec hl	dec hl	djnz loop	ret	;ix should contain the answer  	align 8		;aligns Column_1 to the nearest 256 byte boundary. This makes offsetting easier.Column_1:	ds 16,0 	align 8		;aligns Column_2 to the nearest 256 byte boundary. This makes offsetting easier.Column_2:	ds 16,0
Output:

Output is in hex but is otherwise correct.

0x0242


## ZX Spectrum Basic

Translation of: GW-BASIC
10 DEF FN e(a)=a-INT (a/2)*2-120 DEF FN h(a)=INT (a/2)30 DEF FN d(a)=2*a40 LET x=17: LET y=34: LET tot=050 IF x<1 THEN GO TO 10060 PRINT x;TAB (4);70 IF FN e(x)=0 THEN LET tot=tot+y: PRINT y: GO TO 9080 PRINT "---"90 LET x=FN h(x): LET y=FN d(y): GO TO 50100 PRINT TAB (4);"===",TAB (4);tot