1:- module(punary, [
    2    unary/1,
    3    pow/3,
    4    string_unary/2,
    5    unary_string/2,
    6    add/3,
    7    mul/3,
    8    div/4
    9]).   10
   11:- use_module(purity).   12
   13:- multifile(purity:pcompare/4).   14:- multifile(purity:ptype/2).   15
   16purity:ptype(zero, punary).
   17purity:ptype(c(_), punary).
   18
   19purity:pcompare(punary, A, B, C) :-
   20    unary_compare(A, B, C).
   21
   22% unary_compare(Unary1, Unary2, Comparator).
   23unary_compare(zero, U2, C) :- unary_compare_z(U2, C).
   24unary_compare(c(Z), U2, C) :- unary_compare_c(U2, c(Z), C).
   25
   26unary_compare_z(zero, =).
   27unary_compare_z(c(_), <).
   28
   29unary_compare_c(zero, _, >).
   30unary_compare_c(c(Z2), c(Z1), C) :- 
   31	unary_compare(Z1, Z2, C).
   32
   33% unary(Unary).
   34unary(zero).
   35unary(c(Z)) :- unary(Z).
   36
   37% add(UnaryA, UnaryB, Sum).
   38add(zero, Z, Z).
   39add(c(X), Y, c(Z)) :- 
   40	add(X, Y, Z).
   41
   42% mul(UnaryA, UnaryB, Product)
   43mul(zero, _, zero).
   44mul(c(X), Y, R) :- 
   45	add(Y, S, R), 
   46	mul(X, Y, S).
   47
   48% div(Divide, By, Quotient, Remainder)
   49div(S, D, Q, R) :-
   50	unary_compare(zero, R, C),
   51	unary_div(C, S, D, Q, R).	
   52
   53unary_div(=, S, D, Q, zero) :- 
   54	mul(D, Q, S).
   55unary_div(>, S, D, Q, zero) :- 
   56	mul(D, Q, S).
   57unary_div(<, S, D, Q, R) :- 	
   58	unary_compare(R, D, <),
   59	add(Is, R, S), 
   60	mul(D, Q, Is).
   61
   62% upow(Unary, Factor, Power)
   63pow(zero, zero, zero).
   64pow(N, c(zero), N).
   65pow(N, c(c(Z)), R) :-
   66    mul(N, R1, R),
   67    pow(N, c(Z), R1).
   68
   69%
   70% convert 0 - 9 into a unary value
   71%
   72d_to_u(U, N) :-
   73	d_to_u_(['0','1','2','3','4','5','6','7','8','9'], N, U).
   74
   75d_to_u_([A|T], N, U) :-
   76	pcompare(A, N, C),
   77	d_to_u_(C, N, T, U).
   78
   79d_to_u_(=, _, _, zero).
   80d_to_u_(>, N, T, c(Z)) :-
   81	d_to_u_(T, N, Z).
   82d_to_u_(<, N, T, c(Z)) :-
   83	d_to_u_(T, N, Z).
   84
   85%
   86% convert a unary value below 10 into 0 - 9
   87%
   88u_to_d(U, D) :-
   89	u_to_d_(U, ['0','1','2','3','4','5','6','7','8','9'], D).
   90
   91u_to_d_(zero, [D|_], D).
   92u_to_d_(c(Z), [_|T], D) :-
   93	u_to_d_(Z, T, D).
   94
   95% this is required for overlows, but is not a character that is used
   96unary_10( c(c(c(c(c(c(c(c(c(c(zero)))))))))) ).
   97	
   98% string_unary(String, Unary).
   99string_unary(D, C) :- 
  100	reverse(D, DR),
  101	u_dec_unary_(DR, c(zero), zero, C).
  102
  103u_dec_unary_([], _, Sum, Sum).
  104u_dec_unary_([D|T], Mult, Sum, R) :-	
  105	u_to_d(X, D),
  106	mul(Mult, X, Num),
  107	add(Sum, Num, Sum1),
  108	
  109	unary_10(M),	
  110	mul(Mult, M, NewMult),
  111	
  112	u_dec_unary_(T, NewMult, Sum1, R).
  113
  114	
  115% unary_string(Unary, String).
  116unary_string(U, S) :- 
  117	u_unary_dec(U, c(zero), R),
  118	reverse(R, S).
  119
  120u_unary_dec(zero, _, []).
  121u_unary_dec(c(Z), Mul, [V|T]) :-
  122	unary_10(U_10),
  123	mul(Mul, U_10, NewMul),
  124	div(c(Z), NewMul, LeftOver, R),
  125	u_to_d(R, V),	
  126	u_unary_dec(LeftOver, NewMul, T)