PROGRAM Trig

  REAL pi, dtor, rtod, radians, degrees

  pi = 4.0 * ATAN(1.0)
  dtor = pi / 180.0
  rtod = 180.0 / pi
  radians = pi / 4.0
  degrees = 45.0

  WRITE(*,*) SIN(radians), SIN(degrees*dtor)
  WRITE(*,*) COS(radians), COS(degrees*dtor)
  WRITE(*,*) TAN(radians), TAN(degrees*dtor)
  WRITE(*,*) ASIN(SIN(radians)), ASIN(SIN(degrees*dtor))*rtod
  WRITE(*,*) ACOS(COS(radians)), ACOS(COS(degrees*dtor))*rtod
  WRITE(*,*) ATAN(TAN(radians)), ATAN(TAN(degrees*dtor))*rtod

END PROGRAM Trig


vars(P)={
    my(v=List(),x);
    while(type(P)=="t_POL",
        x=variable(P);
        listput(v,x);
        P=subst(P,x,1)
    );
    Vec(v)
};
truthTable(P)={
    my(var=vars(P),t,b);
    for(i=0,2^#var-1,
        t=eval(P);
        for(j=1,#var,
            b=bittest(i,j-1);
            t=subst(t,var[j],b);
            print1(b)
        );
        print(!!t)
    );
};
truthTable("x+y") \\ OR
truthTable("x*y") \\ AND


program TruthTables;
const
  StackSize = 80;

type
  TVariable = record
    Name: Char;
    Value: Boolean;
  end;

  TStackOfBool = record
    Top: Integer;
    Elements: array [0 .. StackSize - 1] of Boolean;
  end;

var
  Expression: string;
  Variables: array [0 .. 23] of TVariable;
  VariablesLength: Integer;
  i: Integer;
  e: Char;

// Stack manipulation functions
function IsFull(var s: TStackOfBool): Boolean;
begin
  IsFull := s.Top = StackSize - 1;
end;

function IsEmpty(var s: TStackOfBool): Boolean;
begin
  IsEmpty := s.Top = -1;
end;

function Peek(var s: TStackOfBool): Boolean;
begin
  if not IsEmpty(s) then
    Peek := s.Elements[s.Top]
  else
  begin
    Writeln('Stack is empty.');
    Halt;
  end;
end;

procedure Push(var s: TStackOfBool; val: Boolean);
begin
  if not IsFull(s) then
  begin
    Inc(s.Top);
    s.Elements[s.Top] := val;
  end
  else
  begin
    Writeln('Stack is full.');
    Halt;
  end
end;

function Pop(var s: TStackOfBool): Boolean;
begin
  if not IsEmpty(s) then
  begin
    Result := s.Elements[s.Top];
    Dec(s.Top);
  end
  else
  begin
    Writeln;
    Writeln('Stack is empty.');
    Halt;
  end
end;

procedure MakeEmpty(var s: TStackOfBool);
begin
  s.Top := -1;
end;

function ElementsCount(var s: TStackOfBool): Integer;
begin
  ElementsCount := s.Top + 1;
end;

function IsOperator(const c: Char): Boolean;
begin
  IsOperator := (c = '&') or (c = '|') or (c = '!') or (c = '^');
end;

function VariableIndex(const c: Char): Integer;
var
  i: Integer;
begin
  for i := 0 to VariablesLength - 1 do
    if Variables[i].Name = c then
    begin
      VariableIndex := i;
      Exit;
    end;
  VariableIndex := -1;
end;

function EvaluateExpression: Boolean;
var
  i, vi: Integer;
  e: Char;
  s: TStackOfBool;
begin
  MakeEmpty(s);
  for i := 1 to Length(Expression) do
  begin
    e := Expression[i];
    vi := VariableIndex(e);
    if e = 'T' then
      Push(s, True)
    else if e = 'F' then
      Push(s, False)
    else if vi >= 0 then
      Push(s, Variables[vi].Value)
    else
    begin
      {$B+}
      case e of
        '&':
          Push(s, Pop(s) and Pop(s));
        '|':
          Push(s, Pop(s) or Pop(s));
        '!':
          Push(s, not Pop(s));
        '^':
          Push(s, Pop(s) xor Pop(s));
      else
        Writeln;
        Writeln('Non-conformant character ', e, ' in expression.');
        Halt;
      end;
      {$B-}
    end;
  end;
  if ElementsCount(s) <> 1 then
  begin
    Writeln;
    Writeln('Stack should contain exactly one element.');
    Halt;
  end;
  EvaluateExpression := Peek(s);
end;

procedure SetVariables(pos: Integer);
var
  i: Integer;
begin
  if pos > VariablesLength then
  begin
    Writeln;
    Writeln('Argument to SetVariables cannot be greater than the number of variables.');
    Halt;
  end
  else if pos = VariablesLength then
  begin
    for i := 0 to VariablesLength - 1 do
    begin
      if Variables[i].Value then
        Write('T  ')
      else
        Write('F  ');
    end;
    if EvaluateExpression then
      Writeln('T')
    else
      Writeln('F');
  end
  else
  begin
    Variables[pos].Value := False;
    SetVariables(pos + 1);
    Variables[pos].Value := True;
    SetVariables(pos + 1);
  end
end;

// removes space and converts to upper case
procedure ProcessExpression;
var
  i: Integer;
  exprTmp: string;
begin
  exprTmp := '';
  for i := 1 to Length(Expression) do
  begin
    if Expression[i] <> ' ' then
      exprTmp := Concat(exprTmp, UpCase(Expression[i]));
  end;
  Expression := exprTmp
end;

begin
  Writeln('Accepts single-character variables (except for ''T'' and ''F'',');
  Writeln('which specify explicit true or false values), postfix, with');
  Writeln('&|!^ for and, or, not, xor, respectively; optionally');
  Writeln('seperated by space. Just enter nothing to quit.');

  while (True) do
  begin
    Writeln;
    Write('Boolean expression: ');
    ReadLn(Expression);
    ProcessExpression;
    if Length(Expression) = 0 then
      Break;
    VariablesLength := 0;
    for i := 1 to Length(Expression) do
    begin
      e := Expression[i];
      if (not IsOperator(e)) and (e <> 'T') and (e <> 'F') and
        (VariableIndex(e) = -1) then
      begin
        Variables[VariablesLength].Name := e;
        Variables[VariablesLength].Value := False;
        Inc(VariablesLength);
      end;
    end;
    WriteLn;
    if VariablesLength = 0 then
      Writeln('No variables were entered.')
    else
    begin
      for i := 0 to VariablesLength - 1 do
        Write(Variables[i].Name, '  ');
      Writeln(Expression);
      Writeln(StringOfChar('=', VariablesLength * 3 + Length(Expression)));
      SetVariables(0);
    end;
  end;
end.


' FB 1.05.0 Win64

Const pi As Double = 4 * Atn(1)
Dim As Double radians = pi / 4
Dim As Double degrees = 45.0 '' equivalent in degrees
Dim As Double temp

Print "Radians     : "; radians, " ";
Print "Degrees     : "; degrees
Print
Print "Sine        : "; Sin(radians), Sin(degrees * pi / 180)
Print "Cosine      : "; Cos(radians), Cos(degrees * pi / 180)
Print "Tangent     : "; Tan(radians), Tan(degrees * pi / 180)
Print
temp = ASin(Sin(radians))
Print "Arc Sine    : "; temp, temp * 180 / pi
temp = ACos(Cos(radians))
Print "Arc Cosine  : "; temp, temp * 180 / pi
temp = Atn(Tan(radians))
Print "Arc Tangent : "; temp, temp * 180 / pi
Sleep


#!/usr/bin/perl

sub truth_table {
    my $s = shift;
    my (%seen, @vars);
    for ($s =~ /([a-zA-Z_]\w*)/g) {
        $seen{$_} //= do { push @vars, $_; 1 };
    }

    print "\n", join("\t", @vars, $s), "\n", '-' x 40, "\n";
    @vars = map("\$$_", @vars);

    $s =~ s/([a-zA-Z_]\w*)/\$$1/g;
    $s = "print(".join(',"\t", ', map("($_?'T':'F')", @vars, $s)).",\"\\n\")";
    $s = "for my $_ (0, 1) { $s }" for (reverse @vars);
    eval $s;
}

truth_table 'A ^ A_1';
truth_table 'foo & bar | baz';
truth_table 'Jim & (Spock ^ Bones) | Scotty';


# GAP has an improved floating-point support since version 4.5

Pi := Acos(-1.0);

# Or use the built-in constant:
Pi := FLOAT.PI;

r := Pi / 5.0;
d := 36;

Deg := x -> x * Pi / 180;

Sin(r);         Asin(last);
Sin(Deg(d));    Asin(last);
Cos(r);         Acos(last);
Cos(Deg(d));    Acos(last);
Tan(r);         Atan(last);
Tan(Deg(d));    Atan(last);


package main

import (
    "fmt"
    "math"
)

const d = 30.
const r = d * math.Pi / 180

var s = .5
var c = math.Sqrt(3) / 2
var t = 1 / math.Sqrt(3)

func main() {
    fmt.Printf("sin(%9.6f deg) = %f\n", d, math.Sin(d*math.Pi/180))
    fmt.Printf("sin(%9.6f rad) = %f\n", r, math.Sin(r))
    fmt.Printf("cos(%9.6f deg) = %f\n", d, math.Cos(d*math.Pi/180))
    fmt.Printf("cos(%9.6f rad) = %f\n", r, math.Cos(r))
    fmt.Printf("tan(%9.6f deg) = %f\n", d, math.Tan(d*math.Pi/180))
    fmt.Printf("tan(%9.6f rad) = %f\n", r, math.Tan(r))
    fmt.Printf("asin(%f) = %9.6f deg\n", s, math.Asin(s)*180/math.Pi)
    fmt.Printf("asin(%f) = %9.6f rad\n", s, math.Asin(s))
    fmt.Printf("acos(%f) = %9.6f deg\n", c, math.Acos(c)*180/math.Pi)
    fmt.Printf("acos(%f) = %9.6f rad\n", c, math.Acos(c))
    fmt.Printf("atan(%f) = %9.6f deg\n", t, math.Atan(t)*180/math.Pi)
    fmt.Printf("atan(%f) = %9.6f rad\n", t, math.Atan(t))
}


sequence opstack = {}
object token
object op = 0   -- 0 = none
string s        -- the expression being parsed
integer sidx    -- idx to ""
integer ch      -- s[sidx]

procedure err(string msg)
    printf(1,"%s\n%s^ %s\n\nPressEnter...",{s,repeat(' ',sidx-1),msg})
    {} = wait_key()
    abort(0)
end procedure

procedure nxtch()
    sidx += 1
    ch = iff(sidx>length(s)?-1:s[sidx])
end procedure

procedure skipspaces()
    while find(ch," \t\r\n")!=0 do nxtch() end while
end procedure

procedure get_token()
    skipspaces()
    if find(ch,"()!") then
        token = s[sidx..sidx]
        nxtch()
    else
        integer tokstart = sidx
        if ch=-1 then token = "eof" return end if
        while 1 do
            nxtch()
            if ch<'A' then exit end if
        end while
        token = s[tokstart..sidx-1]
    end if
end procedure

procedure Match(string t)
    if token!=t then err(t&" expected") end if
    get_token()
end procedure

procedure PopFactor()
object p2 = opstack[$]
    if op="not" then
        opstack[$] = {0,op,p2}
    else
        opstack = opstack[1..$-1]
        opstack[$] = {opstack[$],op,p2}
    end if
    op = 0
end procedure

sequence names -- {"false","true",...}
sequence flags -- {   0,     1,  ,...}

procedure PushFactor(string t)
    if op!=0 then PopFactor() end if
    integer k = find(t,names)
    if k=0 then
        names = append(names,t)
        k = length(names)
    end if
    opstack = append(opstack,k)
end procedure

procedure PushOp(string t)
    if op!=0 then PopFactor() end if
    op = t
end procedure

procedure Factor()
    if token="not"
    or token="!" then
        get_token()
        Factor()
        if op!=0 then PopFactor() end if
        PushOp("not")
    elsif token="(" then
        get_token()
        Expr(0)
        Match(")")
    elsif not find(token,{"and","or","xor"}) then
        PushFactor(token)
        if ch!=-1 then
            get_token()
        end if
    else
        err("syntax error")
    end if
end procedure

constant {operators,
          precedence} = columnize({{"not",6},
                                   {"and",5},
                                   {"xor",4},
                                   {"or",3}})

procedure Expr(integer p)
    Factor()
    while 1 do
        integer k = find(token,operators)
        if k=0 then exit end if
        integer thisp = precedence[k]
        if thisp<p then exit end if
        get_token()
        Expr(thisp)
        PushOp(operators[k])
    end while
end procedure

function eval(object s)
    if atom(s) then
        if s>=1 then s = flags[s] end if
        return s
    end if
    object {lhs,op,rhs} = s
    lhs = eval(lhs)
    rhs = eval(rhs)
    if op="and" then
        return lhs and rhs
    elsif op="or" then
        return lhs or rhs
    elsif op="xor" then
        return lhs xor rhs
    elsif op="not" then
        return not rhs
    else
        ?9/0
    end if
end function

function next_comb()
    integer fdx = length(flags)
    while flags[fdx]=1 do
        flags[fdx] = 0
        fdx -= 1
    end while
    if fdx<=2 then return false end if  -- all done
    flags[fdx] = 1
    return true
end function

function fmt(bool b)
    return {"0","1"}[b+1]   -- for 0/1
--  return {"F","T"}[b+1]   -- for F/T
end function

procedure test(string expr)
    opstack = {}
    op = 0
    names = {"false","true"}
    s = expr
    sidx = 0
    nxtch()
    get_token()
    Expr(0)
    if op!=0 then PopFactor() end if
    if length(opstack)!=1 then err("some error") end if
    flags = repeat(0,length(names))
    flags[2] = 1 -- set "true" true
    printf(1,"%s  %s\n",{join(names[3..$]),s})
    while 1 do
        for i=3 to length(flags) do -- (skipping true&false)
            printf(1,"%s%s",{fmt(flags[i]),repeat(' ',length(names[i]))})
        end for
        printf(1," %s\n",{fmt(eval(opstack[1]))})
        if not next_comb() then exit end if
    end while
    puts(1,"\n")
end procedure

test("young and not (ugly or poor)")
while 1 do
    puts(1,"input expression:")
    string t = trim(gets(0))
    puts(1,"\n")
    if t="" then exit end if
    test(t)
end while


def radians = Math.PI/4
def degrees = 45

def d2r = { it*Math.PI/180 }
def r2d = { it*180/Math.PI }

println "sin(\u03C0/4) = ${Math.sin(radians)}  == sin(45\u00B0) = ${Math.sin(d2r(degrees))}"
println "cos(\u03C0/4) = ${Math.cos(radians)}  == cos(45\u00B0) = ${Math.cos(d2r(degrees))}"
println "tan(\u03C0/4) = ${Math.tan(radians)}  == tan(45\u00B0) = ${Math.tan(d2r(degrees))}"
println "asin(\u221A2/2) = ${Math.asin(2**(-0.5))} == asin(\u221A2/2)\u00B0 = ${r2d(Math.asin(2**(-0.5)))}\u00B0"
println "acos(\u221A2/2) = ${Math.acos(2**(-0.5))} == acos(\u221A2/2)\u00B0 = ${r2d(Math.acos(2**(-0.5)))}\u00B0"
println "atan(1) = ${Math.atan(1)} == atan(1)\u00B0 = ${r2d(Math.atan(1))}\u00B0"


(de truthTable (Expr)
   (let Vars
      (uniq
         (make
            (setq Expr
               (recur (Expr)  # Convert infix to prefix notation
                  (cond
                     ((atom Expr) (link Expr))
                     ((== 'not (car Expr))
                        (list 'not (recurse (cadr Expr))) )
                     (T
                        (list
                           (cadr Expr)
                           (recurse (car Expr))
                           (recurse (caddr Expr)) ) ) ) ) ) ) )
      (for V Vars
         (prin (align -7 V)) )
      (prinl)
      (bind (mapcar cons Vars)
         (do (** 2 (length Vars))
            (for "V" Vars
               (space (if (print (val "V")) 6 4)) )
            (println (eval Expr))
            (find '(("V") (set "V" (not (val "V")))) Vars) ) ) ) )


/*
    To evaluate the truth table a line of text is inputted and then there are three steps
    Let's say the expression is:
    'not a and (b or c)'

    Step 1: tokenize into atoms and brackets
    eg: Tokenized = [ not, a, and, '(', b, or, c, ')' ].

    Step 2: convert to a term that can be evaluated, and get out the variables
    eg: Expression = op(and, op(not, a), op(or, b, c)), Variables = [ a, b, c ]

    Step 3: permeate over the variables, substituting the values for each var, and evaluate the expression for each permutation
    eg: [ 0, 0, 0]
        op(and, op(not, 0), op(or, 0, 0))
        op(and, 1, op(or, 0, 0))
        op(and, 1, 0)
        0

        [ 0, 0, 1]
        op(and, op(not, 0), op(or, 0, 1))
        op(and, 1, op(or, 0, 0))
        op(and, 1, 1)
        1
*/
truth_table :-
    current_input(In),
    read_line_to_codes(In, Line),
    atom_codes(A, Line),
    atom_chars(A, Chars),

    % parse everything into the form we want
    phrase(tok(Tok), Chars, _),
    phrase(expr(Expr,Vars), Tok, _),
    list_to_set(Vars,VarSet),

    % evaluate
    print_expr(Expr, VarSet), !.

print_expr(Expr, Vars) :-
    % write the header (once)
    maplist(format('~p '), Vars),
    format('~n'),

    % write the results for as many times as there are rows
    eval_expr(Expr, Vars, Tvals, R),
    maplist(format('~p '), Tvals),
    format('~p~n', R),
    fail.
print_expr(_, _).

% Step 1 - tokenize the input into spaces, brackets and atoms
tok([A|As]) --> spaces(_), chars([X|Xs]), {atom_codes(A, [X|Xs])}, spaces(_), tok(As).
tok([A|As]) --> spaces(_), bracket(A), spaces(_), tok(As).
tok([]) --> [].
chars([X|Xs]) --> char(X), { dif(X, ')'), dif(X, '(') }, !, chars(Xs).
chars([]) --> [].
spaces([X|Xs]) --> space(X), !, spaces(Xs).
spaces([]) --> [].
bracket('(') --> ['('].
bracket(')') --> [')'].

% Step 2 - Parse the expression into an evaluable term
expr(op(I, E, E2), V) --> starter(E, V1), infix(I), expr(E2, V2), { append(V1, V2, V) }.
expr(E, V) --> starter(E, V).

starter(op(not, E),V) --> [not], expr(E, V).
starter(E,V) --> ['('], expr(E,V), [')'].
starter(V,[V]) --> variable(V).

infix(or) --> [or].
infix(and) --> [and].
infix(xor) --> [xor].
infix(nand) --> [nand].

variable(V) --> [V], \+ infix(V), \+ bracket(V).
space(' ') --> [' '].
char(X) --> [X], { dif(X, ' ') }.

% Step 3 - evaluate the parsed expression
eval_expr(Expr, Vars, Tvals, R) :-
    length(Vars,Len),
    length(Tvals, Len),
    maplist(truth_val, Tvals),
    eval(Expr, [Tvals,Vars],R).

eval(X, [Vals,Vars], R) :- nth1(N,Vars,X), nth1(N,Vals,R).
eval(op(Op,A,B), V, R) :- eval(A,V,Ae), eval(B,V,Be), e(Op,Ae,Be,R).
eval(op(not,A), V, R) :- eval(A,V,Ae), e(not,Ae,R).

truth_val(0). truth_val(1).

e(or,0,0,0). e(or,0,1,1). e(or,1,0,1). e(or,1,1,1).
e(and,0,0,0). e(and,0,1,0). e(and,1,0,0). e(and,1,1,1).
e(xor,0,0,0). e(xor,0,1,1). e(xor,1,0,1). e(xor,1,1,0).
e(nand,0,0,1). e(nand,0,1,1). e(nand,1,0,1). e(nand,1,1,0).
e(not, 1, 0). e(not, 0, 1).


fromDegrees :: Floating a => a -> a
fromDegrees deg = deg * pi / 180

toDegrees :: Floating a => a -> a
toDegrees rad = rad * 180 / pi

main :: IO ()
main =
  mapM_
    print
    [ sin (pi / 6)
    , sin (fromDegrees 30)
    , cos (pi / 6)
    , cos (fromDegrees 30)
    , tan (pi / 6)
    , tan (fromDegrees 30)
    , asin 0.5
    , toDegrees (asin 0.5)
    , acos 0.5
    , toDegrees (acos 0.5)
    , atan 0.5
    , toDegrees (atan 0.5)
    ]


from itertools import product

while True:
    bexp = input('\nBoolean expression: ')
    bexp = bexp.strip()
    if not bexp:
        print("\nThank you")
        break
    code = compile(bexp, '<string>', 'eval')
    names = code.co_names
    print('\n' + ' '.join(names), ':', bexp)
    for values in product(range(2), repeat=len(names)):
        env = dict(zip(names, values))
        print(' '.join(str(v) for v in values), ':', eval(code, env))


  [ stack ]               is args         (     --> s   )
  [ stack ]               is results      (     --> s   )
  [ stack ]               is function     (     --> s   )

  [ args share times
      [ sp
        2 /mod iff
          [ char t ]
        else
          [ char f ]
        emit ]
    drop
    say " | " ]           is echoargs     ( n   -->     )

  [ args share times
      [ 2 /mod swap ]
    drop ]                is preparestack ( n   --> b*n )

  [ results share times
      [ sp
        iff
          [ char t ]
        else
          [ char f ]
        emit ] ]          is echoresults  ( b*? -->     )

  [ say "Please input your function, preceded" cr
      $ "by the number of arguments and results: " input
    trim nextword quackery args put
    trim nextword quackery results put
    trim build function put
    args share bit times
      [ cr
        i^ echoargs
        i^ preparestack
        function share do
        echoresults ]
     cr
     args release
     results release
     function release ]   is truthtable   (     -->     )


pi = 4.0 * ATAN(1.0)
dtor = pi / 180.0
rtod = 180.0 / pi
radians = pi / 4.0
degrees = 45.0

WRITE(ClipBoard) SIN(radians), SIN(degrees*dtor)
WRITE(ClipBoard) COS(radians), COS(degrees*dtor)
WRITE(ClipBoard) TAN(radians), TAN(degrees*dtor)
WRITE(ClipBoard) ASIN(SIN(radians)), ASIN(SIN(degrees*dtor))*rtod
WRITE(ClipBoard) ACOS(COS(radians)), ACOS(COS(degrees*dtor))*rtod
WRITE(ClipBoard) ATAN(TAN(radians)), ATAN(TAN(degrees*dtor))*rtod


truth_table <- function(x) {
  vars <- unique(unlist(strsplit(x, "[^a-zA-Z]+")))
  vars <- vars[vars != ""]
  perm <- expand.grid(rep(list(c(FALSE, TRUE)), length(vars)))
  names(perm) <- vars
  perm[ , x] <- with(perm, eval(parse(text = x)))
  perm
}

"%^%" <- xor # define unary xor operator

truth_table("!A") # not
##       A    !A
## 1 FALSE  TRUE
## 2  TRUE FALSE

truth_table("A | B") # or
##       A     B A | B
## 1 FALSE FALSE FALSE
## 2  TRUE FALSE  TRUE
## 3 FALSE  TRUE  TRUE
## 4  TRUE  TRUE  TRUE

truth_table("A & B") # and
##       A     B A & B
## 1 FALSE FALSE FALSE
## 2  TRUE FALSE FALSE
## 3 FALSE  TRUE FALSE
## 4  TRUE  TRUE  TRUE

truth_table("A %^% B") # xor
##       A     B A %^% B
## 1 FALSE FALSE   FALSE
## 2  TRUE FALSE    TRUE
## 3 FALSE  TRUE    TRUE
## 4  TRUE  TRUE   FALSE

truth_table("S | (T %^% U)") # 3 variables with brackets
##       S     T     U S | (T %^% U)
## 1 FALSE FALSE FALSE         FALSE
## 2  TRUE FALSE FALSE          TRUE
## 3 FALSE  TRUE FALSE          TRUE
## 4  TRUE  TRUE FALSE          TRUE
## 5 FALSE FALSE  TRUE          TRUE
## 6  TRUE FALSE  TRUE          TRUE
## 7 FALSE  TRUE  TRUE         FALSE
## 8  TRUE  TRUE  TRUE          TRUE

truth_table("A %^% (B %^% (C %^% D))") # 4 variables with nested brackets
##        A     B     C     D A %^% (B %^% (C %^% D))
## 1  FALSE FALSE FALSE FALSE                   FALSE
## 2   TRUE FALSE FALSE FALSE                    TRUE
## 3  FALSE  TRUE FALSE FALSE                    TRUE
## 4   TRUE  TRUE FALSE FALSE                   FALSE
## 5  FALSE FALSE  TRUE FALSE                    TRUE
## 6   TRUE FALSE  TRUE FALSE                   FALSE
## 7  FALSE  TRUE  TRUE FALSE                   FALSE
## 8   TRUE  TRUE  TRUE FALSE                    TRUE
## 9  FALSE FALSE FALSE  TRUE                    TRUE
## 10  TRUE FALSE FALSE  TRUE                   FALSE
## 11 FALSE  TRUE FALSE  TRUE                   FALSE
## 12  TRUE  TRUE FALSE  TRUE                    TRUE
## 13 FALSE FALSE  TRUE  TRUE                   FALSE
## 14  TRUE FALSE  TRUE  TRUE                    TRUE
## 15 FALSE  TRUE  TRUE  TRUE                    TRUE
## 16  TRUE  TRUE  TRUE  TRUE                   FALSE


#lang racket

(define (collect-vars sexpr)
  (sort
   (remove-duplicates
    (let loop ([x sexpr])
      (cond [(boolean? x) '()]
            [(symbol? x) (list x)]
            [(list? x) (append-map loop (cdr x))]
            [else (error 'truth-table "Bad expression: ~e" x)])))
   string<? #:key symbol->string))

(define ns (make-base-namespace))

(define (truth-table sexpr)
  (define vars (collect-vars sexpr))
  (printf "~a => ~s\n" (string-join (map symbol->string vars)) sexpr)
  (for ([i (expt 2 (length vars))])
    (define vals
      (map (λ(x) (eq? #\1 x))
           (reverse (string->list (~r i #:min-width (length vars)
                                        #:pad-string "0"
                                        #:base 2)))))
    (printf "~a => ~a\n" (string-join (map (λ(b) (if b "T" "F")) vals))
            (if (eval `(let (,@(map list vars vals)) ,sexpr) ns) "T" "F"))))

(printf "Enter an expression: ")
(truth-table (read))


use MONKEY-SEE-NO-EVAL;

sub MAIN ($x) {
    my @n = $x.comb(/<ident>/);
    my &fun = EVAL "-> {('\\' «~« @n).join(',')} \{ [{ (|@n,"so $x").join(',') }] \}";

    say (|@n,$x).join("\t");
    .join("\t").say for map &fun, flat map { .fmt("\%0{[email protected]}b").comb».Int».so }, 0 ..^ 2**@n;
    say '';
}


deg = 35         ; arbitrary number of degrees
rad = !dtor*deg  ; system variables !dtor and !radeg convert between rad and deg


invocable all
procedure main()

d := 30          # degrees
r := dtor(d)     # convert to radians

every write(f := !["sin","cos","tan"],"(",r,")=",y := f(r)," ",fi := "a" || f,"(",y,")=",x := fi(y)," rad = ",rtod(x)," deg")
end


/*REXX program displays a truth table of  variables and an expression.   Infix notation */
/*─────────────── is supported with one character propositional constants;  variables   */
/*─────────────── (propositional constants) that are allowed:  A──►Z,  a──►z   except u.*/
/*─────────────── All propositional constants are case insensitive (except lowercase u).*/

parse arg userText                               /*get optional expression from the CL. */
if userText\=''  then do                         /*Got one?   Then show user's stuff.   */
                      call truthTable userText   /*display truth table for the userText.*/
                      exit                       /*we're finished with the user's text. */
                      end

call truthTable  "G ^ H ; XOR"                   /*text after ; is echoed to the output.*/
call truthTable  "i | j ; OR"
call truthTable  "G nxor H ; NXOR"
call truthTable  "k ! t ; NOR"
call truthTable  "p & q ; AND"
call truthTable  "e ¡ f ; NAND"
call truthTable  "S | (T ^ U)"
call truthTable  "(p=>q) v (q=>r)"
call truthTable  "A ^ (B ^ (C ^ D))"
exit                                             /*quit while we're ahead,  by golly.   */

    /* ↓↓↓ no way, Jose. ↓↓↓ */                  /* [↓]  shows a 32,768 line truth table*/
call truthTable  "A^ (B^ (C^ (D^ (E^ (F^ (G^ (H^ (I^ (J^ (L^ (L^ (M^ (N^O)  ))))))))))))"
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
truthTable: procedure; parse arg $ ';' comm 1 $o;        $o=  strip($o);      hdrPCs=
               $= translate(strip($), '|', "v");         $u=  $;              upper $u
              $u= translate($u, '()()()', "[]{}«»");     $$.= 0;              PCs=
            @abc= 'abcdefghijklmnopqrstuvwxyz';          @abcU= @abc;         upper @abcU

/* ╔═════════════════════╦════════════════════════════════════════════════════════════╗
   ║                     ║                  bool(bitsA, bitsB, BF)                    ║
   ║                     ╟────────────────────────────────────────────────────────────╢
   ║                     ║ performs the boolean function  BF    ┌──────┬─────────┐    ║
   ║                     ║      on the   A   bitstring          │  BF  │ common  │    ║
   ║                     ║    with the   B   bitstring.         │ value│  name   │    ║
   ║                     ║                                      ├──────┼─────────┤    ║
   ║                     ║ BF   must be a  one to four bit      │ 0000 │boolfalse│    ║
   ║                     ║ value  (from  0000 ──► 1111),        │ 0001 │ and     │    ║
   ║  This boxed table   ║ leading zeroes can be omitted.       │ 0010 │ NaIMPb  │    ║
   ║ was re─constructed  ║                                      │ 0011 │ boolB   │    ║
   ║   from an old IBM   ║ BF   may have multiple values (one   │ 0100 │ NbIMPa  │    ║
   ║    publicastion:    ║ for each pair of bitstrings):        │ 0101 │ boolA   │    ║
   ║                     ║                                      │ 0110 │ xor     │    ║
   ║   "PL/I Language    ║  ┌──────┬──────┬───────────────┐     │ 0111 │ or      │    ║
   ║   Specifications"   ║  │ Abit │ Bbit │   returns     │     │ 1000 │ nor     │    ║
   ║                     ║  ├──────┼──────┼───────────────┤     │ 1001 │ nxor    │    ║
   ║                     ║  │   0  │   0  │ 1st bit in BF │     │ 1010 │ notB    │    ║
   ║                     ║  │   0  │   1  │ 2nd bit in BF │     │ 1011 │ bIMPa   │    ║
   ║   ─── March 1969.   ║  │   1  │   0  │ 3rd bit in BF │     │ 1100 │ notA    │    ║
   ║                     ║  │   1  │   1  │ 4th bit in BF │     │ 1101 │ aIMPb   │    ║
   ║                     ║  └──────┴──────┴───────────────┘     │ 1110 │ nand    │    ║
   ║                     ║                                      │ 1111 │booltrue │    ║
   ║                     ║                                   ┌──┴──────┴─────────┤    ║
   ║                     ║                                   │ A  0101           │    ║
   ║                     ║                                   │ B  0011           │    ║
   ║                     ║                                   └───────────────────┘    ║
   ╚═════════════════════╩════════════════════════════════════════════════════════════╝ */

  @= 'ff'x                                       /* [↓]  ───── infix operators (0──►15) */
  op.=                                           /*Note:   a  single quote  (')  wasn't */
                                                 /*            implemented for negation.*/
  op.0 = 'false  boolFALSE'                      /*unconditionally  FALSE               */
  op.1 = '&      and *'                          /* AND,  conjunction                   */
  op.2 = 'naimpb NaIMPb'                         /*not A implies B                      */
  op.3 = 'boolb  boolB'                          /*B  (value of)                        */
  op.4 = 'nbimpa NbIMPa'                         /*not B implies A                      */
  op.5 = 'boola  boolA'                          /*A  (value of)                        */
  op.6 = '&&     xor % ^'                        /* XOR,  exclusive OR                  */
  op.7 = '|      or + v'                         /*  OR,  disjunction                   */
  op.8 = 'nor    nor ! ↓'                        /* NOR,  not OR,  Pierce operator      */
  op.9 = 'xnor   xnor nxor'                      /*NXOR,  not exclusive OR,  not XOR    */
  op.10= 'notb   notB'                           /*not B  (value of)                    */
  op.11= 'bimpa  bIMPa'                          /*    B  implies A                     */
  op.12= 'nota   notA'                           /*not A  (value of)                    */
  op.13= 'aimpb  aIMPb'                          /*    A  implies B                     */
  op.14= 'nand   nand ¡ ↑'                       /*NAND,  not AND,  Sheffer operator    */
  op.15= 'true   boolTRUE'                       /*unconditionally   TRUE               */
                                                 /*alphabetic names that need changing. */
  op.16= '\   NOT ~ ─ . ¬'                       /* NOT,  negation                      */
  op.17= '>   GT'                                /*conditional                          */
  op.18= '>=  GE ─> => ──> ==>'   "1a"x          /*conditional;     (see note below.)──┐*/
  op.19= '<   LT'                                /*conditional                         │*/
  op.20= '<=  LE <─ <= <── <=='                  /*conditional                         │*/
  op.21= '\=  NE ~= ─= .= ¬='                    /*conditional                         │*/
  op.22= '=   EQ EQUAL EQUALS ='  "1b"x          /*bi─conditional;  (see note below.)┐ │*/
  op.23= '0   boolTRUE'                          /*TRUEness                          │ │*/
  op.24= '1   boolFALSE'                         /*FALSEness                         ↓ ↓*/
                                                 /* [↑] glphys  '1a'x  and  "1b"x  can't*/
                                                 /*     displayed under most DOS' & such*/
    do jj=0  while  op.jj\=='' | jj<16           /*change opers ──► into what REXX likes*/
    new= word(op.jj, 1)                          /*obtain the 1st token of  infex table.*/
                                                 /* [↓]  process the rest of the tokens.*/
      do kk=2  to words(op.jj)                   /*handle each of the tokens separately.*/
      _=word(op.jj, kk);          upper _        /*obtain another token from infix table*/
      if wordpos(_, $u)==0   then iterate        /*no such animal in this string.       */
      if datatype(new, 'm')  then new!= @        /*it            needs to be transcribed*/
                             else new!= new      /*it  doesn't   need   "  "     "      */
      $u= changestr(_, $u, new!)                 /*transcribe the function (maybe).     */
      if [email protected]  then $u= changeFunc($u,@,new)  /*use the internal boolean name.       */
      end   /*kk*/
    end     /*jj*/

  $u=translate($u, '()', "{}")                   /*finish cleaning up the transcribing. */

        do jj=1  for length(@abcU)               /*see what variables are being used.   */
        _= substr(@abcU, jj, 1)                  /*use the available upercase aLphabet. */
        if pos(_,$u) == 0  then iterate          /*Found one?    No, then keep looking. */
        $$.jj= 1                                 /*found:  set upper bound for it.      */
          PCs= PCs _                             /*also, add to propositional constants.*/
        hdrPCs=hdrPCS center(_,length('false'))  /*build a PC header for transcribing.  */
        end   /*jj*/

  ptr= '_────►_'                                 /*a (text) pointer for the truth table.*/
   $u= PCs '('$u")"                              /*separate the  PCs  from expression.  */
  hdrPCs= substr(hdrPCs, 2)                      /*create a header for the  PCs.        */
  say hdrPCs left('', length(ptr) - 1)   $o      /*display  PC  header and expression.  */
  say copies('───── ', words(PCs))    left('', length(ptr) -2)  copies('─', length($o))
                                                 /*Note:  "true"s:  are right─justified.*/
                do a=0  to $$.1
                 do b=0  to $$.2
                  do c=0  to $$.3
                   do d=0  to $$.4
                    do e=0  to $$.5
                     do f=0  to $$.6
                      do g=0  to $$.7
                       do h=0  to $$.8
                        do i=0  to $$.9
                         do j=0  to $$.10
                          do k=0  to $$.11
                           do l=0  to $$.12
                            do m=0  to $$.13
                             do n=0  to $$.14
                              do o=0  to $$.15
                               do p=0  to $$.16
                                do q=0  to $$.17
                                 do r=0  to $$.18
                                  do s=0  to $$.19
                                   do t=0  to $$.20
                                    do u=0  to $$.21
                                     do !=0  to $$.22
                                      do w=0  to $$.23
                                       do x=0  to $$.24
                                        do y=0  to $$.25
                                         do z=0  to $$.26;         interpret   '_='   $u
 /*evaluate truth T.*/
                                         _= changestr(1, _, '_true') /*convert 1──►_true*/
                                         _= changestr(0, _, 'false') /*convert 0──►false*/
                                         _= insert(ptr,  _, wordindex(_, words(_) )  - 1)
                                         say translate(_, , '_')     /*display truth tab*/
                                         end   /*z*/
                                        end    /*y*/
                                       end     /*x*/
                                      end      /*w*/
                                     end       /*v*/
                                    end        /*u*/
                                   end         /*t*/
                                  end          /*s*/
                                 end           /*r*/
                                end            /*q*/
                               end             /*p*/
                              end              /*o*/
                             end               /*n*/
                            end                /*m*/
                           end                 /*l*/
                          end                  /*k*/
                         end                   /*j*/
                        end                    /*i*/
                       end                     /*h*/
                      end                      /*g*/
                     end                       /*f*/
                    end                        /*e*/
                   end                         /*d*/
                  end                          /*c*/
                 end                           /*b*/
                end                            /*a*/
  say;  say
  return
/*──────────────────────────────────────────────────────────────────────────────────────*/
scan: procedure; parse arg x,at;      L= length(x);   t=L;    Lp=0;    apost=0;    quote=0
      if at<0  then      do;   t=1;   x= translate(x, '()', ")(")
                         end                      /* [↓]  get 1 or 2 chars at location J*/

            do j=abs(at)  to t  by sign(at);      _=substr(x, j ,1);   __=substr(x, j, 2)
            if quote             then do;  if _\=='"'    then iterate
                                           if __=='""'   then do;  j= j+1;  iterate;  end
                                           quote=0;  iterate
                                      end
            if apost             then do;  if _\=="'"    then iterate
                                           if __=="''"   then do;  j= j+1;  iterate;  end
                                           apost=0;   iterate
                                      end
            if _== '"'           then do;  quote=1;   iterate;  end
            if _== "'"           then do;  apost=1;   iterate;  end
            if _== ' '           then iterate
            if _== '('           then do;  Lp= Lp+1;  iterate;  end
            if Lp\==0            then do;  if _==')'     then Lp= Lp-1;     iterate;  end
            if datatype(_, 'U')  then return j - (at<0)
            if at<0              then return j + 1              /*is   _    uppercase ? */
            end   /*j*/

      return min(j, L)
/*──────────────────────────────────────────────────────────────────────────────────────*/
changeFunc: procedure;  parse arg z, fC, newF ;           funcPos= 0

              do forever
              funcPos= pos(fC, z, funcPos + 1);           if funcPos==0  then return z
              origPos= funcPos
                    z= changestr(fC, z, ",'"newF"',") /*arg 3 ≡  ",'" || newF || "-',"  */
              funcPos= funcPos + length(newF) + 4
                where= scan(z, funcPos)       ;           z= insert(    '}',  z,  where)
                where= scan(z, 1 - origPos)   ;           z= insert('bool{',  z,  where)
              end   /*forever*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
bool: procedure; arg a,?,b                              /* ◄─── ARG uppercases all args.*/

                          select                        /*SELECT chooses which function.*/
                 /*0*/    when ? == 'FALSE'   then  return 0
                 /*1*/    when ? == 'AND'     then  return a & b
                 /*2*/    when ? == 'NAIMPB'  then  return \ (\a & \b)
                 /*3*/    when ? == 'BOOLB'   then  return b
                 /*4*/    when ? == 'NBIMPA'  then  return \ (\b & \a)
                 /*5*/    when ? == 'BOOLA'   then  return a
                 /*6*/    when ? == 'XOR'     then  return a && b
                 /*7*/    when ? == 'OR'      then  return a |  b
                 /*8*/    when ? == 'NOR'     then  return \ (a |  b)
                 /*9*/    when ? == 'XNOR'    then  return \ (a && b)
                 /*a*/    when ? == 'NOTB'    then  return \ b
                 /*b*/    when ? == 'BIMPA'   then  return \ (b & \a)
                 /*c*/    when ? == 'NOTA'    then  return \ a
                 /*d*/    when ? == 'AIMPB'   then  return \ (a & \b)
                 /*e*/    when ? == 'NAND'    then  return \ (a &  b)
                 /*f*/    when ? == 'TRUE'    then  return 1
                          otherwise                 return -13
                          end   /*select*/              /* [↑]  error, unknown function.*/


public class Trig {
        public static void main(String[] args) {
                //Pi / 4 is 45 degrees. All answers should be the same.
                double radians = Math.PI / 4;
                double degrees = 45.0;
                //sine
                System.out.println(Math.sin(radians) + " " + Math.sin(Math.toRadians(degrees)));
                //cosine
                System.out.println(Math.cos(radians) + " " + Math.cos(Math.toRadians(degrees)));
                //tangent
                System.out.println(Math.tan(radians) + " " + Math.tan(Math.toRadians(degrees)));
                //arcsine
                double arcsin = Math.asin(Math.sin(radians));
                System.out.println(arcsin + " " + Math.toDegrees(arcsin));
                //arccosine
                double arccos = Math.acos(Math.cos(radians));
                System.out.println(arccos + " " + Math.toDegrees(arccos));
                //arctangent
                double arctan = Math.atan(Math.tan(radians));
                System.out.println(arctan + " " + Math.toDegrees(arctan));
        }
}


loop do
  print "\ninput a boolean expression (e.g. 'a & b'): "
  expr = gets.strip.downcase
  break if expr.empty?

  vars = expr.scan(/\p{Alpha}+/)
  if vars.empty?
    puts "no variables detected in your boolean expression"
    next
  end

  vars.each {|v| print "#{v}\t"}
  puts "| #{expr}"

  prefix = []
  suffix = []
  vars.each do |v|
    prefix << "[false, true].each do |#{v}|"
    suffix << "end"
  end

  body = vars.inject("puts ") {|str, v| str + "#{v}.to_s + '\t' + "}
  body += '"| " + eval(expr).to_s'

  eval (prefix + [body] + suffix).join("\n")
end


use std::{
    collections::HashMap,
    fmt::{Display, Formatter},
    iter::FromIterator,
};

// Generic expression evaluation automaton and expression formatting support

#[derive(Clone, Debug)]
pub enum EvaluationError<T> {
    NoResults,
    TooManyResults,
    OperatorFailed(T),
}

pub trait Operator<T> {
    type Err;

    fn execute(&self, stack: &mut Vec<T>) -> Result<(), Self::Err>;
}

#[derive(Clone, Copy, Debug)]
enum Element<O> {
    Operator(O),
    Variable(usize),
}

#[derive(Clone, Debug)]
pub struct Expression<O> {
    elements: Vec<Element<O>>,
    symbols: Vec<String>,
}

impl<O> Expression<O> {
    pub fn evaluate<T>(
        &self,
        mut bindings: impl FnMut(usize) -> T,
    ) -> Result<T, EvaluationError<O::Err>>
    where
        O: Operator<T>,
    {
        let mut stack = Vec::new();

        for element in self.elements.iter() {
            match element {
                Element::Variable(index) => stack.push(bindings(*index)),
                Element::Operator(op) => op
                    .execute(&mut stack)
                    .map_err(EvaluationError::OperatorFailed)?,
            }
        }

        match stack.pop() {
            Some(result) if stack.is_empty() => Ok(result),
            Some(_) => Err(EvaluationError::TooManyResults),
            None => Err(EvaluationError::NoResults),
        }
    }

    pub fn symbols(&self) -> &[String] {
        &self.symbols
    }

    pub fn formatted(&self) -> Result<String, EvaluationError<O::Err>>
    where
        O: Operator<Formatted>,
    {
        self.evaluate(|index| Formatted(self.symbols[index].clone()))
            .map(|formatted| formatted.0)
    }
}

#[derive(Clone, Debug)]
pub struct Formatted(pub String);

impl Display for Formatted {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl<O> Display for Expression<O>
where
    O: Operator<Formatted>,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self.formatted() {
            Ok(result) => write!(f, "{}", result),
            Err(_) => write!(f, "<malformed expression>"),
        }
    }
}

// Generic parts of the parsing machinery

#[derive(Clone, Copy, Debug)]
pub enum Token<'a, O> {
    LBrace,
    RBrace,
    Operator(O),
    Variable(&'a str),
    Malformed(&'a str),
}

pub type Symbol<'a, O> = (&'a str, bool, Token<'a, O>);

#[derive(Debug)]
pub struct Tokens<'a, O> {
    source: &'a str,
    symbols: &'a [Symbol<'a, O>],
}

impl<'a, O> Tokens<'a, O> {
    pub fn new(source: &'a str, symbols: &'a [Symbol<'a, O>]) -> Self {
        Self { source, symbols }
    }
}

impl<'a, O: Clone> Iterator for Tokens<'a, O> {
    type Item = Token<'a, O>;

    fn next(&mut self) -> Option<Self::Item> {
        self.source = self.source.trim_start();

        let symbol = self.symbols.iter().find_map(|(symbol, word, token)| {
            if self.source.starts_with(symbol) {
                let end = symbol.len();

                if *word {
                    match &self.source[end..].chars().next() {
                        Some(c) if !c.is_whitespace() => return None,
                        _ => (),
                    }
                }

                Some((token, end))
            } else {
                None
            }
        });

        if let Some((token, end)) = symbol {
            self.source = &self.source[end..];
            Some(token.clone())
        } else {
            match self.source.chars().next() {
                Some(c) if c.is_alphabetic() => {
                    let end = self
                        .source
                        .char_indices()
                        .find_map(|(i, c)| Some(i).filter(|_| !c.is_alphanumeric()))
                        .unwrap_or_else(|| self.source.len());

                    let result = &self.source[0..end];
                    self.source = &self.source[end..];
                    Some(Token::Variable(result))
                }

                Some(c) => {
                    let end = c.len_utf8();
                    let result = &self.source[0..end];
                    self.source = &self.source[end..];
                    Some(Token::Malformed(result))
                }

                None => None,
            }
        }
    }
}

pub trait WithPriority {
    type Priority;

    fn priority(&self) -> Self::Priority;
}

impl<'a, O> FromIterator<Token<'a, O>> for Result<Expression<O>, Token<'a, O>>
where
    O: WithPriority,
    O::Priority: Ord,
{
    fn from_iter<T: IntoIterator<Item = Token<'a, O>>>(tokens: T) -> Self {
        let mut token_stack = Vec::new();
        let mut indices = HashMap::new();
        let mut symbols = Vec::new();
        let mut elements = Vec::new();

        'outer: for token in tokens {
            match token {
                Token::Malformed(_) => return Err(token),
                Token::LBrace => token_stack.push(token),
                Token::RBrace => {
                    // Flush all operators to the matching LBrace
                    while let Some(token) = token_stack.pop() {
                        match token {
                            Token::LBrace => continue 'outer,
                            Token::Operator(op) => elements.push(Element::Operator(op)),
                            _ => return Err(token),
                        }
                    }
                }

                Token::Variable(name) => {
                    let index = indices.len();
                    let symbol = name.to_string();
                    let index = *indices.entry(symbol.clone()).or_insert_with(|| {
                        symbols.push(symbol);
                        index
                    });

                    elements.push(Element::Variable(index));
                }

                Token::Operator(ref op) => {
                    while let Some(token) = token_stack.pop() {
                        match token {
                            Token::Operator(pop) if op.priority() < pop.priority() => {
                                elements.push(Element::Operator(pop));
                            }

                            Token::Operator(pop) => {
                                token_stack.push(Token::Operator(pop));
                                break;
                            }

                            _ => {
                                token_stack.push(token);
                                break;
                            }
                        }
                    }

                    token_stack.push(token);
                }
            }
        }

        // Handle leftovers
        while let Some(token) = token_stack.pop() {
            match token {
                Token::Operator(op) => elements.push(Element::Operator(op)),
                _ => return Err(token),
            }
        }

        Ok(Expression { elements, symbols })
    }
}

// Definition of Boolean operators

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Boolean {
    Or,
    Xor,
    And,
    Not,
}

impl Display for Boolean {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            Self::Or => "∨",
            Self::And => "∧",
            Self::Not => "¬",
            Self::Xor => "⩛",
        };

        write!(f, "{}", s)
    }
}

impl WithPriority for Boolean {
    type Priority = u8;

    fn priority(&self) -> u8 {
        match self {
            Self::Or => 0,
            Self::Xor => 1,
            Self::And => 2,
            Self::Not => 3,
        }
    }
}

#[derive(Clone, Debug)]
pub enum BooleanError {
    StackUnderflow,
}

impl Operator<bool> for Boolean {
    type Err = BooleanError;

    fn execute(&self, stack: &mut Vec<bool>) -> Result<(), Self::Err> {
        let mut pop = || stack.pop().ok_or(BooleanError::StackUnderflow);

        let result = match self {
            Boolean::Or => pop()? | pop()?,
            Boolean::And => pop()? & pop()?,
            Boolean::Xor => pop()? ^ pop()?,
            Boolean::Not => !pop()?,
        };

        stack.push(result);
        Ok(())
    }
}

impl Operator<Formatted> for Boolean {
    type Err = BooleanError;

    fn execute(&self, stack: &mut Vec<Formatted>) -> Result<(), Self::Err> {
        let mut pop = || stack.pop().ok_or(BooleanError::StackUnderflow);

        let result = match self {
            Boolean::Not => format!("{}{}", Boolean::Not, pop()?),

            binary_operator => {
                // The stack orders the operands backwards, so to format them
                // properly, we have to count with the reversed popping order
                let b = pop()?;
                let a = pop()?;
                format!("({} {} {})", a, binary_operator, b)
            }
        };

        stack.push(Formatted(result));
        Ok(())
    }
}

impl Boolean {
    // It is important for the tokens to be ordered by their parsing priority (if
    // some operator was a prefix of another operator, the prefix must come later)
    const SYMBOLS: [Symbol<'static, Boolean>; 18] = [
        ("(", false, Token::LBrace),
        (")", false, Token::RBrace),
        ("|", false, Token::Operator(Boolean::Or)),
        ("∨", false, Token::Operator(Boolean::Or)),
        ("or", true, Token::Operator(Boolean::Or)),
        ("OR", true, Token::Operator(Boolean::Or)),
        ("&", false, Token::Operator(Boolean::And)),
        ("∧", false, Token::Operator(Boolean::And)),
        ("and", true, Token::Operator(Boolean::And)),
        ("AND", true, Token::Operator(Boolean::And)),
        ("!", false, Token::Operator(Boolean::Not)),
        ("¬", false, Token::Operator(Boolean::Not)),
        ("not", true, Token::Operator(Boolean::Not)),
        ("NOT", true, Token::Operator(Boolean::Not)),
        ("^", false, Token::Operator(Boolean::Xor)),
        ("⩛", false, Token::Operator(Boolean::Xor)),
        ("xor", true, Token::Operator(Boolean::Xor)),
        ("XOR", true, Token::Operator(Boolean::Xor)),
    ];

    pub fn tokenize(s: &str) -> Tokens<'_, Boolean> {
        Tokens::new(s, &Self::SYMBOLS)
    }

    pub fn parse<'a>(s: &'a str) -> Result<Expression<Boolean>, Token<'a, Boolean>> {
        Self::tokenize(s).collect()
    }
}

// Finally the table printing

fn print_truth_table(s: &str) -> Result<(), std::borrow::Cow<'_, str>> {
    let expression = Boolean::parse(s).map_err(|e| format!("Parsing failed at token {:?}", e))?;

    let formatted = expression
        .formatted()
        .map_err(|_| "Malformed expression detected.")?;

    let var_count = expression.symbols().len();
    if var_count > 64 {
        return Err("Too many variables to list.".into());
    }

    let column_widths = {
        // Print header and compute the widths of columns
        let mut widths = Vec::with_capacity(var_count);

        for symbol in expression.symbols() {
            print!("{}  ", symbol);
            widths.push(symbol.chars().count() + 2); // Include spacing
        }

        println!("{}", formatted);
        let width = widths.iter().sum::<usize>() + formatted.chars().count();
        (0..width).for_each(|_| print!("-"));
        println!();

        widths
    };

    // Choose the bit extraction order for the more traditional table ordering
    let var_value = |input, index| (input >> (var_count - 1 - index)) & 1 ^ 1;
    // Use counter to enumerate all bit combinations
    for var_values in 0u64..(1 << var_count) {
        for (var_index, width) in column_widths.iter().enumerate() {
            let value = var_value(var_values, var_index);
            print!("{:<width$}", value, width = width);
        }

        match expression.evaluate(|var_index| var_value(var_values, var_index) == 1) {
            Ok(result) => println!("{}", if result { "1" } else { "0" }),
            Err(e) => println!("{:?}", e),
        }
    }

    println!();
    Ok(())
}

fn main() {
    loop {
        let input = {
            println!("Enter the expression to parse (or nothing to quit):");
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).unwrap();
            println!();
            input
        };

        if input.trim().is_empty() {
            break;
        }

        if let Err(e) = print_truth_table(&input) {
            eprintln!("{}\n", e);
        }
    }
}


var
 radians = Math.PI / 4, // Pi / 4 is 45 degrees. All answers should be the same.
 degrees = 45.0,
 sine = Math.sin(radians),
 cosine = Math.cos(radians),
 tangent = Math.tan(radians),
 arcsin = Math.asin(sine),
 arccos = Math.acos(cosine),
 arctan = Math.atan(tangent);

// sine
window.alert(sine + " " + Math.sin(degrees * Math.PI / 180));
// cosine
window.alert(cosine + " " + Math.cos(degrees * Math.PI / 180));
// tangent
window.alert(tangent + " " + Math.tan(degrees * Math.PI / 180));
// arcsine
window.alert(arcsin + " " + (arcsin * 180 / Math.PI));
// arccosine
window.alert(arccos + " " + (arccos * 180 / Math.PI));
// arctangent
window.alert(arctan + " " + (arctan * 180 / Math.PI));


loop {
  var expr = Sys.readln("\nBoolean expression (e.g. 'a & b'): ").strip.lc
  break if expr.is_empty;

  var vars = expr.scan(/[[:alpha:]]+/)
  if (vars.is_empty) {
    say "no variables detected in your boolean expression"
    next
  }

  var prefix = [];
  var suffix = [];

  vars.each { |v|
    print "#{v}\t"
    prefix << "[false, true].each { |#{v}|"
    suffix << "}"
  }
  say "| #{expr}"

  var body = ("say (" + vars.map{|v| v+",'\t'," }.join + " '| ', #{expr})")
  eval(prefix + [body] + suffix -> join("\n"))
}


[:repeat |
    expr := Stdin
              request:'Enter boolean expression (name variables a,b,c...):'
              defaultAnswer:'a|b'.
    ast := Parser parseExpression:expr inNameSpace:nil onError:repeat.
    "
     ensure that only boolean logic operations are inside (sandbox)
    "
    (ast messageSelectors asSet
        conform:[:each | #( '|' '&' 'not' 'xor:' '==>' ) includes:each])
          ifFalse:repeat.
] valueWithRestart.

"
 extract variables from the AST as a collection
 (i.e. if user entered 'a & (b | x)', we get #('a' 'b' 'x')
"
varNames := StringCollection streamContents:[:s | ast variableNodesDo:[:each | s nextPut:each name]].

"
 generate code for a block (aka lambda) to evaluate it; this makes a string like:
   [:a :b :x | a & (b | x) ]
"
code := '[' , ((varNames collect:[:nm | ':',nm]) asString), ' | ' , expr , ']'.

"
 eval the code, to get the block
"
func := Parser evaluate:code.

'Truth table for %s:\n' printf:{expr} on:Stdout.
'===================\n' printf:{} on:Stdout.
(varNames,{' result'}) do:[:each | '|%6s' printf:{each} on:Stdout].
Stdout cr.
Stdout next:(varNames size + 1)*7 put:$-.
Stdout cr.

"
 now print with all combinations
"
allCombinationsDo :=
    [:remainingVars :valuesIn :func |
        remainingVars isEmpty ifTrue:[
            valuesIn do:[:each | '|%6s' printf:{each}on:Stdout].
            '|%6s\n' printf:{ func valueWithArguments:valuesIn} on:Stdout.
        ] ifFalse:[
            #(false true) do:[:each |
                allCombinationsDo value:(remainingVars from:2)
                                  value:(valuesIn copyWith:each)
                                  value:func.
            ].
        ].
    ].

allCombinationsDo value:varNames value:#() value:func


help Math
Math.method(...)
Commands performing math operations on numbers
Methods: abs acos asin atan atan2 ceil cos exp floor log max min pow random round sin sqrt tan


package require Tcl 8.5

puts -nonewline "Enter a boolean expression: "
flush stdout
set exp [gets stdin]

# Generate the nested loops as the body of a lambda term.
set vars [lsort -unique [regexp -inline -all {\$\w+} $exp]]
set cmd [list format [string repeat "%s\t" [llength $vars]]%s]
append cmd " {*}\[[list subst $vars]\] \[[list expr $exp]\]"
set cmd "puts \[$cmd\]"
foreach v [lreverse $vars] {
    set cmd [list foreach [string range $v 1 end] {0 1} $cmd]
}

puts [join $vars \t]\tResult
apply [list {} $cmd]


Imports System.Text

Module Module1
    Structure Operator_
        Public ReadOnly Symbol As Char
        Public ReadOnly Precedence As Integer
        Public ReadOnly Arity As Integer
        Public ReadOnly Fun As Func(Of Boolean, Boolean, Boolean)

        Public Sub New(symbol As Char, precedence As Integer, f As Func(Of Boolean, Boolean))
            Me.New(symbol, precedence, 1, Function(l, r) f(r))
        End Sub

        Public Sub New(symbol As Char, precedence As Integer, f As Func(Of Boolean, Boolean, Boolean))
            Me.New(symbol, precedence, 2, f)
        End Sub

        Public Sub New(symbol As Char, precedence As Integer, arity As Integer, fun As Func(Of Boolean, Boolean, Boolean))
            Me.Symbol = symbol
            Me.Precedence = precedence
            Me.Arity = arity
            Me.Fun = fun
        End Sub
    End Structure

    Public Class OperatorCollection
        Implements IEnumerable(Of Operator_)

        ReadOnly operators As IDictionary(Of Char, Operator_)

        Public Sub New(operators As IDictionary(Of Char, Operator_))
            Me.operators = operators
        End Sub

        Public Sub Add(symbol As Char, precedence As Integer, fun As Func(Of Boolean, Boolean))
            operators.Add(symbol, New Operator_(symbol, precedence, fun))
        End Sub
        Public Sub Add(symbol As Char, precedence As Integer, fun As Func(Of Boolean, Boolean, Boolean))
            operators.Add(symbol, New Operator_(symbol, precedence, fun))
        End Sub

        Public Sub Remove(symbol As Char)
            operators.Remove(symbol)
        End Sub

        Public Function GetEnumerator() As IEnumerator(Of Operator_) Implements IEnumerable(Of Operator_).GetEnumerator
            Return operators.Values.GetEnumerator
        End Function

        Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
            Return GetEnumerator()
        End Function
    End Class

    Structure BitSet
        Private ReadOnly bits As Integer

        Public Sub New(bits As Integer)
            Me.bits = bits
        End Sub

        Public Shared Operator +(bs As BitSet, v As Integer) As BitSet
            Return New BitSet(bs.bits + v)
        End Operator

        Default Public ReadOnly Property Test(index As Integer) As Boolean
            Get
                Return (bits And (1 << index)) <> 0
            End Get
        End Property
    End Structure

    Public Class TruthTable
        Enum TokenType
            Unknown
            WhiteSpace
            Constant
            Operand
            Operator_
            LeftParenthesis
            RightParenthesis
        End Enum

        ReadOnly falseConstant As Char
        ReadOnly trueConstant As Char
        ReadOnly operatorDict As New Dictionary(Of Char, Operator_)

        Public ReadOnly Operators As OperatorCollection

        Sub New(falseConstant As Char, trueConstant As Char)
            Me.falseConstant = falseConstant
            Me.trueConstant = trueConstant
            Operators = New OperatorCollection(operatorDict)
        End Sub

        Private Function TypeOfToken(c As Char) As TokenType
            If Char.IsWhiteSpace(c) Then
                Return TokenType.WhiteSpace
            End If
            If c = "("c Then
                Return TokenType.LeftParenthesis
            End If
            If c = ")"c Then
                Return TokenType.RightParenthesis
            End If
            If c = trueConstant OrElse c = falseConstant Then
                Return TokenType.Constant
            End If
            If operatorDict.ContainsKey(c) Then
                Return TokenType.Operator_
            End If
            If Char.IsLetter(c) Then
                Return TokenType.Operand
            End If

            Return TokenType.Unknown
        End Function

        Private Function Precedence(op As Char) As Integer
            Dim o As New Operator_
            If operatorDict.TryGetValue(op, o) Then
                Return o.Precedence
            Else
                Return Integer.MinValue
            End If
        End Function

        Public Function ConvertToPostfix(infix As String) As String
            Dim stack As New Stack(Of Char)
            Dim postfix As New StringBuilder()
            For Each c In infix
                Dim type = TypeOfToken(c)
                Select Case type
                    Case TokenType.WhiteSpace
                        Continue For
                    Case TokenType.Constant, TokenType.Operand
                        postfix.Append(c)
                    Case TokenType.Operator_
                        Dim precedence_ = Precedence(c)
                        While stack.Count > 0 AndAlso Precedence(stack.Peek()) > precedence_
                            postfix.Append(stack.Pop())
                        End While
                        stack.Push(c)
                    Case TokenType.LeftParenthesis
                        stack.Push(c)
                    Case TokenType.RightParenthesis
                        Dim top As Char
                        While stack.Count > 0
                            top = stack.Pop()
                            If top = "("c Then
                                Exit While
                            Else
                                postfix.Append(top)
                            End If
                        End While
                        If top <> "("c Then
                            Throw New ArgumentException("No matching left parenthesis.")
                        End If
                    Case Else
                        Throw New ArgumentException("Invalid character: " + c)
                End Select
            Next
            While stack.Count > 0
                Dim top = stack.Pop()
                If top = "("c Then
                    Throw New ArgumentException("No matching right parenthesis.")
                End If
                postfix.Append(top)
            End While
            Return postfix.ToString
        End Function

        Private Function Evaluate(expression As Stack(Of Char), values As BitSet, parameters As IDictionary(Of Char, Integer)) As Boolean
            If expression.Count = 0 Then
                Throw New ArgumentException("Invalid expression.")
            End If
            Dim c = expression.Pop()
            Dim type = TypeOfToken(c)
            While type = TokenType.WhiteSpace
                c = expression.Pop()
                type = TypeOfToken(c)
            End While
            Select Case type
                Case TokenType.Constant
                    Return c = trueConstant
                Case TokenType.Operand
                    Return values(parameters(c))
                Case TokenType.Operator_
                    Dim right = Evaluate(expression, values, parameters)
                    Dim op = operatorDict(c)
                    If op.Arity = 1 Then
                        Return op.Fun(right, right)
                    End If

                    Dim left = Evaluate(expression, values, parameters)
                    Return op.Fun(left, right)
                Case Else
                    Throw New ArgumentException("Invalid character: " + c)
            End Select

            Return False
        End Function

        Public Iterator Function GetTruthTable(expression As String, Optional isPostfix As Boolean = False) As IEnumerable(Of String)
            If String.IsNullOrWhiteSpace(expression) Then
                Throw New ArgumentException("Invalid expression.")
            End If
            REM Maps parameters to an index in BitSet
            REM Makes sure they appear in the truth table in the order they first appear in the expression
            Dim parameters = expression _
                .Where(Function(c) TypeOfToken(c) = TokenType.Operand) _
                .Distinct() _
                .Reverse() _
                .Select(Function(c, i) Tuple.Create(c, i)) _
                .ToDictionary(Function(p) p.Item1, Function(p) p.Item2)

            Dim count = parameters.Count
            If count > 32 Then
                Throw New ArgumentException("Cannot have more than 32 parameters.")
            End If
            Dim header = If(count = 0, expression, String.Join(" ", parameters.OrderByDescending(Function(p) p.Value).Select(Function(p) p.Key)) & " " & expression)
            If Not isPostfix Then
                expression = ConvertToPostfix(expression)
            End If

            Dim values As BitSet
            Dim stack As New Stack(Of Char)(expression.Length)

            Dim loopy = 1 << count
            While loopy > 0
                For Each token In expression
                    stack.Push(token)
                Next
                Dim result = Evaluate(stack, values, parameters)
                If Not IsNothing(header) Then
                    If stack.Count > 0 Then
                        Throw New ArgumentException("Invalid expression.")
                    End If
                    Yield header
                    header = Nothing
                End If

                Dim line = If(count = 0, "", " ") + If(result, trueConstant, falseConstant)
                line = String.Join(" ", Enumerable.Range(0, count).Select(Function(i) If(values(count - i - 1), trueConstant, falseConstant))) + line
                Yield line
                values += 1
                ''''''''''''''''''''''''''''
                loopy -= 1
            End While
        End Function

        Public Sub PrintTruthTable(expression As String, Optional isPostfix As Boolean = False)
            Try
                For Each line In GetTruthTable(expression, isPostfix)
                    Console.WriteLine(line)
                Next
            Catch ex As ArgumentException
                Console.WriteLine(expression + "   " + ex.Message)
            End Try
        End Sub
    End Class

    Sub Main()
        Dim tt As New TruthTable("F"c, "T"c)
        tt.Operators.Add("!"c, 6, Function(r) Not r)
        tt.Operators.Add("&"c, 5, Function(l, r) l And r)
        tt.Operators.Add("^"c, 4, Function(l, r) l Xor r)
        tt.Operators.Add("|"c, 3, Function(l, r) l Or r)
        REM add a crazy operator
        Dim rng As New Random
        tt.Operators.Add("?"c, 6, Function(r) rng.NextDouble() < 0.5)
        Dim expressions() = {
            "!!!T",
            "?T",
            "F & x | T",
            "F & (x | T",
            "F & x | T)",
            "a ! (a & a)",
            "a | (a * a)",
            "a ^ T & (b & !c)"
        }
        For Each expression In expressions
            tt.PrintTruthTable(expression)
            Console.WriteLine()
        Next

        REM Define a different language
        tt = New TruthTable("0"c, "1"c)
        tt.Operators.Add("-"c, 6, Function(r) Not r)
        tt.Operators.Add("^"c, 5, Function(l, r) l And r)
        tt.Operators.Add("v"c, 3, Function(l, r) l Or r)
        tt.Operators.Add(">"c, 2, Function(l, r) Not l Or r)
        tt.Operators.Add("="c, 1, Function(l, r) l = r)
        expressions = {
            "-X v 0 = X ^ 1",
            "(H > M) ^ (S > H) > (S > M)"
        }
        For Each expression In expressions
            tt.PrintTruthTable(expression)
            Console.WriteLine()
        Next
    End Sub

End Module


# v0.6.0

rad = π / 4
deg = 45.0

@show rad deg
@show sin(rad) sin(deg2rad(deg))
@show cos(rad) cos(deg2rad(deg))
@show tan(rad) tan(deg2rad(deg))
@show asin(sin(rad)) asin(sin(rad)) |> rad2deg
@show acos(cos(rad)) acos(cos(rad)) |> rad2deg
@show atan(tan(rad)) atan(tan(rad)) |> rad2deg


// version 1.1.2

import java.lang.Math.*

fun main(args: Array<String>) {
    val radians = Math.PI / 4.0
    val degrees = 45.0
    val conv = Math.PI / 180.0
    val f = "%1.15f"
    var inverse: Double

    println("                Radians              Degrees")
    println("Angle      : ${f.format(radians)}\t ${f.format(degrees)}\n")
    println("Sin        : ${f.format(sin(radians))}\t  ${f.format(sin(degrees * conv))}")
    println("Cos        : ${f.format(cos(radians))}\t  ${f.format(cos(degrees * conv))}")
    println("Tan        : ${f.format(tan(radians))}\t  ${f.format(tan(degrees * conv))}\n")
    inverse = asin(sin(radians))
    println("ASin(Sin)  : ${f.format(inverse)}\t ${f.format(inverse / conv)}")
    inverse = acos(cos(radians))
    println("ACos(Cos)  : ${f.format(inverse)}\t ${f.format(inverse / conv)}")
    inverse = atan(tan(radians))
    println("ATan(Tan)  : ${f.format(inverse)}\t ${f.format(inverse / conv)}")
}


import "/dynamic" for Struct
import "/ioutil" for Input
import "/seq" for Stack
import "/str" for Str

var Variable = Struct.create("Variable", ["name", "value"])

// use integer constants as bools don't support bitwise operators
var FALSE = 0
var TRUE = 1

var expr = ""
var variables = []

var isOperator = Fn.new { |op| "&|!^".contains(op) }

var isVariable = Fn.new { |s| variables.map { |v| v.name }.contains(s) }

var evalExpression = Fn.new {
    var stack = Stack.new()
    for (e in expr) {
        var v
        if (e == "T") {
            v = TRUE
        } else if (e == "F") {
            v = FALSE
        } else if (isVariable.call(e)) {
            var vs = variables.where { |v| v.name == e }.toList
            if (vs.count != 1) Fiber.abort("Can only be one variable with name %(e).")
            v = vs[0].value
        } else if (e == "&") {
            v = stack.pop() & stack.pop()
        } else if (e == "|") {
            v = stack.pop() | stack.pop()
        } else if (e == "!") {
            v = (stack.pop() == TRUE) ? FALSE : TRUE
        } else if (e == "^") {
            v = stack.pop() ^ stack.pop()
        } else {
            Fiber.abort("Non-conformant character %(e) in expression")
        }
        stack.push(v)
    }
    if (stack.count != 1) Fiber.abort("Something went wrong!")
    return stack.peek()
}

var setVariables // recursive
setVariables = Fn.new { |pos|
    var vc = variables.count
    if (pos > vc) Fiber.abort("Argument cannot exceed %(vc).")
    if (pos == vc) {
        var vs = variables.map { |v| (v.value == TRUE) ? "T" : "F" }.toList
        var es = (evalExpression.call() == TRUE) ? "T" : "F"
        System.print("%(vs.join("  "))  %(es)")
        return
    }
    variables[pos].value = FALSE
    setVariables.call(pos + 1)
    variables[pos].value = TRUE
    setVariables.call(pos + 1)
}

System.print("Accepts single-character variables (except for 'T' and 'F',")
System.print("which specify explicit true or false values), postfix, with")
System.print("&|!^ for and, or, not, xor, respectively; optionally")
System.print("seperated by spaces or tabs. Just enter nothing to quit.")

while (true) {
    expr = Input.text("\nBoolean expression: ")
    if (expr == "") return
    expr = Str.upper(expr).replace(" ", "").replace("\t", "")
    variables.clear()
    for (e in expr) {
        if (!isOperator.call(e) && !"TF".contains(e) && !isVariable.call(e)) {
            variables.add(Variable.new(e, FALSE))
        }
    }
    if (variables.isEmpty) return
    var vs = variables.map { |v| v.name }.join("  ")
    System.print("\n%(vs)  %(expr)")
    var h = vs.count + expr.count + 2
    System.print("=" * h)
    setVariables.call(0)
}


PROGRAM "truthtables"
VERSION "0.001"

$$MaxTop = 80

TYPE VARIABLE
  STRING*1 .name
  SBYTE .value
END TYPE

TYPE STACKOFBOOL
  SSHORT .top
  SBYTE .elements[$$MaxTop]
END TYPE

DECLARE FUNCTION Entry()
INTERNAL FUNCTION IsOperator(c$)
INTERNAL FUNCTION VariableIndex(c$)
INTERNAL FUNCTION SetVariables(pos%)
INTERNAL FUNCTION ProcessExpression()
INTERNAL FUNCTION EvaluateExpression()

' Stack manipulation functions
INTERNAL FUNCTION IsFull(STACKOFBOOL @s)
INTERNAL FUNCTION IsEmpty(STACKOFBOOL @s)
INTERNAL FUNCTION Peek(STACKOFBOOL @s)
INTERNAL FUNCTION Push(STACKOFBOOL @s, val@)
INTERNAL FUNCTION Pop(STACKOFBOOL @s)
INTERNAL FUNCTION MakeEmpty(STACKOFBOOL @s)
INTERNAL FUNCTION ElementsCount(STACKOFBOOL @s)

FUNCTION Entry()
  SHARED VARIABLE variables[]
  SHARED variablesLength%
  SHARED expression$

  DIM variables[23]
  PRINT "Accepts single-character variables (except for 'T' and 'F',"
  PRINT "which specify explicit true or false values), postfix, with"
  PRINT "&|!^ for and, or, not, xor, respectively; optionally"
  PRINT "seperated by space. Just enter nothing to quit."
  DO
    PRINT
    expression$ = INLINE$("Boolean expression: ")
    ProcessExpression()
    IF LEN(expression$) = 0 THEN
      EXIT DO
    END IF
    variablesLength% = 0
    FOR i% = 0 TO LEN(expression$) - 1
      e$ = CHR$(expression${i%})
      IF (!IsOperator(e$)) && (e$ <> "T") && (e$ <> "F") && (VariableIndex(e$) = -1) THEN
        variables[variablesLength%].name = LEFT$(e$, 1)
        variables[variablesLength%].value = $$FALSE
        INC variablesLength%
      END IF
    NEXT i%
    PRINT
    IF variablesLength% = 0 THEN
      PRINT "No variables were entered."
    ELSE
      FOR i% = 0 TO variablesLength% - 1
        PRINT variables[i%].name; "  ";
      NEXT i%
      PRINT expression$
      PRINT CHR$(ASC("="), variablesLength% * 3 + LEN(expression$))
      SetVariables(0)
    END IF
  LOOP
END FUNCTION

' Removes space and converts to upper case
FUNCTION ProcessExpression()
  SHARED expression$
  '
  exprTmp$ = ""
  FOR i% = 0 TO LEN(expression$) - 1
    IF CHR$(expression${i%}) <> " " THEN
      exprTmp$ = exprTmp$ + UCASE$(CHR$(expression${i%}))
    END IF
  NEXT i%
  expression$ = exprTmp$
END FUNCTION

FUNCTION IsOperator(c$)
  RETURN (c$ = "&") || (c$ = "|") || (c$ = "!") || (c$ = "^")
END FUNCTION

FUNCTION VariableIndex(c$)
  SHARED VARIABLE variables[]
  SHARED variablesLength%
  '
  FOR i% = 0 TO variablesLength% - 1
    IF variables[i%].name = c$ THEN
      RETURN i%
    END IF
  NEXT i%
  RETURN -1
END FUNCTION

FUNCTION SetVariables(pos%)
  SHARED VARIABLE variables[]
  SHARED variablesLength%
  '
  SELECT CASE TRUE
    CASE pos% > variablesLength%:
      PRINT
      PRINT "Argument to SetVariables cannot be greater than the number of variables."
      QUIT(1)
    CASE pos% = variablesLength%:
      FOR i% = 0 TO variablesLength% - 1
        IF variables[i%].value THEN
          PRINT "T  ";
        ELSE
          PRINT "F  ";
        END IF
      NEXT i%
      IF EvaluateExpression() THEN
        PRINT "T"
      ELSE
        PRINT "F"
      END IF
    CASE ELSE:
      variables[pos%].value = $$FALSE
      SetVariables(pos% + 1)
      variables[pos%].value = $$TRUE
      SetVariables(pos% + 1)
  END SELECT
END FUNCTION

FUNCTION EvaluateExpression()
  SHARED VARIABLE variables[]
  SHARED expression$
  STACKOFBOOL s
  '
  MakeEmpty(@s)
  FOR i% = 0 TO LEN(expression$) - 1
    e$ = CHR$(expression${i%})
    vi% = VariableIndex(e$)
    SELECT CASE TRUE
      CASE e$ = "T":
        Push(@s, $$TRUE)
      CASE e$ = "F":
        Push(@s, $$FALSE)
      CASE vi% >= 0:
        Push(@s, variables[vi%].value)
      CASE ELSE:
        SELECT CASE e$
          CASE "&":
            Push(@s, Pop(@s) & Pop(@s))
          CASE "|":
            Push(@s, Pop(@s) | Pop(@s))
          CASE "!":
            Push(@s, !Pop(@s))
          CASE "^":
            Push(@s, Pop(@s) ^ Pop(@s))
          CASE ELSE:
            PRINT
            PRINT "Non-conformant character "; e$; " in expression.";
            QUIT(1)
        END SELECT
    END SELECT
  NEXT i%
  IF ElementsCount(@s) <> 1 THEN
    PRINT
    PRINT "Stack should contain exactly one element."
    QUIT(1)
  END IF
  RETURN Peek(@s)
END FUNCTION

FUNCTION IsFull(STACKOFBOOL s)
  RETURN s.top = $$MaxTop
END FUNCTION

FUNCTION IsEmpty(STACKOFBOOL s)
  RETURN s.top = -1
END FUNCTION

FUNCTION Peek(STACKOFBOOL s)
  IF !IsEmpty(@s) THEN
    RETURN s.elements[s.top]
  ELSE
    PRINT "Stack is empty."
    QUIT(1)
  END IF
END FUNCTION

FUNCTION Push(STACKOFBOOL s, val@)
  IF !IsFull(@s) THEN
    INC s.top
    s.elements[s.top] = val@
  ELSE
    PRINT "Stack is full."
    QUIT(1)
  END IF
END FUNCTION

FUNCTION Pop(STACKOFBOOL s)
  IF !IsEmpty(@s) THEN
    res@ = s.elements[s.top]
    DEC s.top
    RETURN res@
  ELSE
    PRINT
    PRINT "Stack is empty."
    QUIT(1)
  END IF
END FUNCTION

FUNCTION MakeEmpty(STACKOFBOOL s)
  s.top = -1
END FUNCTION

FUNCTION ElementsCount(STACKOFBOOL s)
  RETURN s.top + 1
END FUNCTION
END PROGRAM


pi = ACS(-1)
radians = pi / 4.0
rtod = 180 / pi
degrees = radians * rtod
dtor = pi / 180

'LB works in radians, so degrees require conversion
print "Sin:   ";SIN(radians);"   "; SIN(degrees*dtor)
print "Cos:  ";COS(radians);"    "; COS(degrees*dtor)
print "Tan:  ";TAN(radians);"                   ";TAN(degrees*dtor)
print "-  Inverse functions:"
print "Asn:  ";ASN(SIN(radians));" Rad,  "; ASN(SIN(degrees*dtor))*rtod;" Deg"
print "Acs:  ";ACS(COS(radians));" Rad,  "; ACS(COS(degrees*dtor))*rtod;" Deg"
print "Atn:  ";ATN(TAN(radians));" Rad,  "; ATN(TAN(degrees*dtor))*rtod;" Deg"


print sin 45
print cos 45
print arctan 1
make "pi (radarctan 0 1) * 2 ; based on quadrant if uses two parameters
print radsin :pi / 4
print radcos :pi / 4
print 4 * radarctan 1


:- object(trignomeric_functions).

    :- public(show/0).
    show :-
        % standard trignomeric functions work with radians
        write('sin(pi/4.0) = '), SIN is sin(pi/4.0), write(SIN), nl,
        write('cos(pi/4.0) = '), COS is cos(pi/4.0), write(COS), nl,
        write('tan(pi/4.0) = '), TAN is tan(pi/4.0), write(TAN), nl,
        write('asin(sin(pi/4.0)) = '), ASIN is asin(sin(pi/4.0)), write(ASIN), nl,
        write('acos(cos(pi/4.0)) = '), ACOS is acos(cos(pi/4.0)), write(ACOS), nl,
        write('atan(tan(pi/4.0)) = '), ATAN is atan(tan(pi/4.0)), write(ATAN), nl,
        write('atan2(3,4) = '), ATAN2 is atan2(3,4), write(ATAN2), nl.

:- end_object.


print(math.cos(1), math.sin(1), math.tan(1), math.atan(1), math.atan2(3, 4))


Sin[1]
Cos[1]
Tan[1]
ArcSin[1]
ArcCos[1]
ArcTan[1]
Sin[90 Degree]
Cos[90 Degree]
Tan[90 Degree]


function trigExample(angleDegrees)

    angleRadians = angleDegrees * (pi/180);

    disp(sprintf('sin(%f)= %f\nasin(%f)= %f',[angleRadians sin(angleRadians) sin(angleRadians) asin(sin(angleRadians))]));
    disp(sprintf('sind(%f)= %f\narcsind(%f)= %f',[angleDegrees sind(angleDegrees) sind(angleDegrees) asind(sind(angleDegrees))]));
    disp('-----------------------');
    disp(sprintf('cos(%f)= %f\nacos(%f)= %f',[angleRadians cos(angleRadians) cos(angleRadians) acos(cos(angleRadians))]));
    disp(sprintf('cosd(%f)= %f\narccosd(%f)= %f',[angleDegrees cosd(angleDegrees) cosd(angleDegrees) acosd(cosd(angleDegrees))]));
    disp('-----------------------');
    disp(sprintf('tan(%f)= %f\natan(%f)= %f',[angleRadians tan(angleRadians) tan(angleRadians) atan(tan(angleRadians))]));
    disp(sprintf('tand(%f)= %f\narctand(%f)= %f',[angleDegrees tand(angleDegrees) tand(angleDegrees) atand(tand(angleDegrees))]));
end


a: %pi / 3;
[sin(a), cos(a), tan(a), sec(a), csc(a), cot(a)];

b: 1 / 2;
[asin(b), acos(b), atan(b), asec(1 / b), acsc(1 / b), acot(b)];

/* Hyperbolic functions are also available */
a: 1 / 2;
[sinh(a), cosh(a), tanh(a), sech(a), csch(a), coth(a)], numer;
[asinh(a), acosh(1 / a), atanh(a), asech(a), acsch(a), acoth(1 / a)], numer;


local radians = pi / 4
local degrees = 45.0

--sine
print (sin (radToDeg radians))
print (sin degrees)
--cosine
print (cos (radToDeg radians))
print (cos degrees)
--tangent
print (tan (radToDeg radians))
print (tan degrees)
--arcsine
print (asin (sin (radToDeg radians)))
print (asin (sin degrees))
--arccosine
print (acos (cos (radToDeg radians)))
print (acos (cos degrees))
--arctangent
print (atan (tan (radToDeg radians)))
print (atan (tan degrees))


Pi := 3.14159;
vardef torad expr x = Pi*x/180 enddef;       % conversions
vardef todeg expr x = 180x/Pi enddef;
vardef sin expr x = sind(todeg(x)) enddef;   % radians version of sind
vardef cos expr x = cosd(todeg(x)) enddef;   % and cosd

vardef sign expr x = if x>=0: 1 else: -1 fi enddef; % commodity

vardef tand expr x =                      % tan with arg in degree
  if cosd(x) = 0:
    infinity * sign(sind(x))
  else: sind(x)/cosd(x) fi enddef;
vardef tan expr x = tand(todeg(x)) enddef; % arg in rad

% INVERSE

% the arc having x as tanget is that between x-axis and a line
% from the center to the point (1, x); MF angle says this
vardef atand expr x = angle(1,x) enddef;
vardef atan expr x = torad(atand(x))  enddef;  % rad version

% known formula to express asin and acos in function of
% atan; a+-+b stays for sqrt(a^2 - b^2) (defined in plain MF)
vardef asin expr x =  2atan(x/(1+(1+-+x)))  enddef;
vardef acos expr x =  2atan((1+-+x)/(1+x))  enddef;

vardef asind expr x =  todeg(asin(x))  enddef; % degree versions
vardef acosd expr x =  todeg(acos(x))  enddef;

% commodity
def outcompare(expr a, b) = message decimal a & " = " & decimal b enddef;

% output tests
outcompare(torad(60), Pi/3);
outcompare(todeg(Pi/6), 30);

outcompare(Pi/3, asin(sind(60)));
outcompare(30, acosd(cos(Pi/6)));
outcompare(45, atand(tand(45)));
outcompare(Pi/4, atan(tand(45)));

outcompare(sin(Pi/3), sind(60));
outcompare(cos(Pi/4), cosd(45));
outcompare(tan(Pi/3), tand(60));

end


pi3 = pi/3
degToRad = pi/180
print "sin PI/3 radians = " + sin(pi3)
print "sin 60 degrees = " + sin(60*degToRad)
print "arcsin 0.5 in radians = " + asin(0.5)
print "arcsin 0.5 in degrees = " + asin(0.5)/degToRad
print "cos PI/3 radians = " + cos(pi3)
print "cos 60 degrees = " + cos(60*degToRad)
print "arccos 0.5 in radians = " + acos(0.5)
print "arccos 0.5 in degrees = " + acos(0.5)/degToRad
print "tan PI/3 radians = " + tan(pi3)
print "tan 60 degrees = " + tan(60*degToRad)
print "arctan 0.5 in radians = " + atan(0.5)
print "arctan 0.5 in degrees = " + atan(0.5)/degToRad


sin	С/П	Вx	cos	С/П	Вx	tg	С/П	Вx	arcsin
С/П	Вx	arccos	С/П	Вx	arctg	С/П


MODULE Trig;
FROM RealMath IMPORT pi,sin,cos,tan,arctan,arccos,arcsin;
FROM RealStr IMPORT RealToStr;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;

PROCEDURE WriteReal(v : REAL);
VAR buf : ARRAY[0..31] OF CHAR;
BEGIN
    RealToStr(v, buf);
    WriteString(buf)
END WriteReal;

VAR theta : REAL;
BEGIN
    theta := pi / 4.0;

    WriteString("theta: ");
    WriteReal(theta);
    WriteLn;

    WriteString("sin: ");
    WriteReal(sin(theta));
    WriteLn;

    WriteString("cos: ");
    WriteReal(cos(theta));
    WriteLn;

    WriteString("tan: ");
    WriteReal(tan(theta));
    WriteLn;

    WriteString("arcsin: ");
    WriteReal(arcsin(sin(theta)));
    WriteLn;

    WriteString("arccos: ");
    WriteReal(arccos(cos(theta)));
    WriteLn;

    WriteString("arctan: ");
    WriteReal(arctan(tan(theta)));
    WriteLn;

    ReadChar
END Trig.


/* NetRexx */
options replace format comments java crossref symbols nobinary utf8

numeric digits 30

parse 'Radians Degrees angle' RADIANS DEGREES ANGLE .;
parse 'sine cosine tangent arcsine arccosine arctangent' SINE COSINE TANGENT ARCSINE ARCCOSINE ARCTANGENT .

trigVals = ''
trigVals[RADIANS, ANGLE     ] = (Rexx Math.PI) / 4 -- Pi/4 == 45 degrees
trigVals[DEGREES, ANGLE     ] = 45.0
trigVals[RADIANS, SINE      ] = (Rexx Math.sin(trigVals[RADIANS, ANGLE]))
trigVals[DEGREES, SINE      ] = (Rexx Math.sin(Math.toRadians(trigVals[DEGREES, ANGLE])))
trigVals[RADIANS, COSINE    ] = (Rexx Math.cos(trigVals[RADIANS, ANGLE]))
trigVals[DEGREES, COSINE    ] = (Rexx Math.cos(Math.toRadians(trigVals[DEGREES, ANGLE])))
trigVals[RADIANS, TANGENT   ] = (Rexx Math.tan(trigVals[RADIANS, ANGLE]))
trigVals[DEGREES, TANGENT   ] = (Rexx Math.tan(Math.toRadians(trigVals[DEGREES, ANGLE])))
trigVals[RADIANS, ARCSINE   ] = (Rexx Math.asin(trigVals[RADIANS, SINE]))
trigVals[DEGREES, ARCSINE   ] = (Rexx Math.toDegrees(Math.acos(trigVals[DEGREES, SINE])))
trigVals[RADIANS, ARCCOSINE ] = (Rexx Math.acos(trigVals[RADIANS, COSINE]))
trigVals[DEGREES, ARCCOSINE ] = (Rexx Math.toDegrees(Math.acos(trigVals[DEGREES, COSINE])))
trigVals[RADIANS, ARCTANGENT] = (Rexx Math.atan(trigVals[RADIANS, TANGENT]))
trigVals[DEGREES, ARCTANGENT] = (Rexx Math.toDegrees(Math.atan(trigVals[DEGREES, TANGENT])))

say        ' '.right(12)'|' RADIANS.right(17)                           '|' DEGREES.right(17)                           '|'
say      ANGLE.right(12)'|' trigVals[RADIANS, ANGLE     ].format(4, 12) '|' trigVals[DEGREES, ANGLE     ].format(4, 12) '|'
say       SINE.right(12)'|' trigVals[RADIANS, SINE      ].format(4, 12) '|' trigVals[DEGREES, SINE      ].format(4, 12) '|'
say     COSINE.right(12)'|' trigVals[RADIANS, COSINE    ].format(4, 12) '|' trigVals[DEGREES, COSINE    ].format(4, 12) '|'
say    TANGENT.right(12)'|' trigVals[RADIANS, TANGENT   ].format(4, 12) '|' trigVals[DEGREES, TANGENT   ].format(4, 12) '|'
say    ARCSINE.right(12)'|' trigVals[RADIANS, ARCSINE   ].format(4, 12) '|' trigVals[DEGREES, ARCSINE   ].format(4, 12) '|'
say  ARCCOSINE.right(12)'|' trigVals[RADIANS, ARCCOSINE ].format(4, 12) '|' trigVals[DEGREES, ARCCOSINE ].format(4, 12) '|'
say ARCTANGENT.right(12)'|' trigVals[RADIANS, ARCTANGENT].format(4, 12) '|' trigVals[DEGREES, ARCTANGENT].format(4, 12) '|'
say

return


import math, strformat

let rad = Pi/4
let deg = 45.0

echo &"Sine:       {sin(rad):.10f} {sin(degToRad(deg)):13.10f}"
echo &"Cosine :    {cos(rad):.10f} {cos(degToRad(deg)):13.10f}"
echo &"Tangent:    {tan(rad):.10f} {tan(degToRad(deg)):13.10f}"
echo &"Arcsine:    {arcsin(sin(rad)):.10f} {radToDeg(arcsin(sin(degToRad(deg)))):13.10f}"
echo &"Arccosine:  {arccos(cos(rad)):.10f} {radToDeg(arccos(cos(degToRad(deg)))):13.10f}"
echo &"Arctangent: {arctan(tan(rad)):.10f} {radToDeg(arctan(tan(degToRad(deg)))):13.10f}"


let pi = 4. *. atan 1.

let radians = pi /. 4.
let degrees = 45.;;

Printf.printf "%f %f\n" (sin radians) (sin (degrees *. pi /. 180.));;
Printf.printf "%f %f\n" (cos radians) (cos (degrees *. pi /. 180.));;
Printf.printf "%f %f\n" (tan radians) (tan (degrees *. pi /. 180.));;
let arcsin = asin (sin radians);;
Printf.printf "%f %f\n" arcsin (arcsin *. 180. /. pi);;
let arccos = acos (cos radians);;
Printf.printf "%f %f\n" arccos (arccos *. 180. /. pi);;
let arctan = atan (tan radians);;
Printf.printf "%f %f\n" arctan (arctan *. 180. /. pi);;


function d = degree(rad)
  d = 180*rad/pi;
endfunction

r = pi/3;
rd = degree(r);

funcs = { "sin", "cos", "tan", "sec", "cot", "csc" };
ifuncs = { "asin", "acos", "atan", "asec", "acot", "acsc" };

for i = 1 : numel(funcs)
  v = arrayfun(funcs{i}, r);
  vd = arrayfun(strcat(funcs{i}, "d"), rd);
  iv = arrayfun(ifuncs{i}, v);
  ivd = arrayfun(strcat(ifuncs{i}, "d"), vd);
  printf("%s(%f) = %s(%f) = %f (%f)\n",
                    funcs{i}, r, strcat(funcs{i}, "d"), rd, v, vd);
  printf("%s(%f) = %f\n%s(%f) = %f\n",
                    ifuncs{i}, v, iv,
                    strcat(ifuncs{i}, "d"), vd, ivd);
endfor


import: math

: testTrigo
| rad deg hyp z |
   Pi 4 / ->rad
   45.0   ->deg
    0.5   ->hyp

   System.Out rad sin << " - " << deg asRadian sin << cr
   System.Out rad cos << " - " << deg asRadian cos << cr
   System.Out rad tan << " - " << deg asRadian tan << cr

   printcr

   rad sin asin ->z
   System.Out z << " - " << z asDegree << cr

   rad cos acos ->z
   System.Out z << " - " << z asDegree << cr

   rad tan atan ->z
   System.Out z << " - " << z asDegree << cr

   printcr

   System.Out hyp sinh << " - " << hyp sinh asinh << cr
   System.Out hyp cosh << " - " << hyp cosh acosh << cr
   System.Out hyp tanh << " - " << hyp tanh atanh << cr ;


rxm.cls                                                    20 March 2014

The distribution of ooRexx contains a function package called rxMath
that provides the computation of trigonometric and some other functions.
Based on the underlying C-library the precision of the returned values
is limited to 16 digits. Close observation show that sometimes the last
one to three digits of the returned values are not correct.
Many years ago I experimented with implementing these functions in Rexx
with its virtually unlimited precision.
The rxm class is intended to provide the same functionality as rxMath
with no limit on the specified or implied precision.

Functions in class rxm and invocation syntax are the same as
in the rxMath library. They are implemented as routines which
perform the checking of argument values and invoke the corresponding
methods. Here is a list of the supported functions and a concise
syntax specification.

The arguments are represented by these letters:

x is the value for which the respective function must be evaluated.
b and c for RxCalcPower are base and exponent, respectively.

p if specified is the desired precision (number of digits) in the result.
  It can be any integer from 1 to 999999.
  See below for the default used.

u if specified, is the unit of x given to the trigonometric functions
  or the unit of the value returned by the Arcus functions.
  It can be 'R', 'D', or 'G' for radians, degrees, or grades, respectively.
  See below for the default used.

Trigonometric functions:

• rxmCos(x[,[p][,u]])
• rxmCotan(x[,[p][,u]])
• rxmSin(x[,[p][,u]])
• rxmTan(x[,[p][,u]])

Arcus functions:

• rxmArcCos(x[,[p][,u]])
• rxmArcSin(x[,[p][,u]])
• rxmArcTan(x[,[p][,u]])

Hyperbolic functions:

• rxmCosH(x[,p])
• rxmSinH(x[,p])
• rxmTanH(x[,p])

• rxmExp(x[,p])      e**x
• rxmLog(x[,p])      Natural logarithm of x
• rxmLog10(x[,p])    Brigg's logarithm of x
• rxmSqrt(x[,p])     Square root of x

• rxmPower(b,c[,p])  b**c

• rxmPi([p])         pi to the specified or default precision

Values used for p and u if these are omitted in the invocation
==============================================================

The directive ::REQUIRES rxm.cls creates an instance of the class
  .local~my.rxm=.rxm~new(16,"D")
which sets the defaults for p=16 and u='D'.
These are used when p or u are omitted in a function invocation.
They can be changed by changing the respective class attributes as follows:
  .locaL~my.rxm~precision=50
  .locaL~my.rxm~type='R'
The current setting of these attributes can be retrieved as follows:
  .locaL~my.rxm~precision()
  .locaL~my.rxm~type()

While I tried to get full compatibility there remain a few
(actually very few) differences:

  rxCalcTan(90) raises the Syntax condition (will be fixed in the next ooRexx release)
  rxCalcexp(x) limits x to 709. or so and returns '+infinity' for larger exponents


declare
  PI = 3.14159265

  fun {FromDegrees Deg}
     Deg * PI / 180.
  end

  fun {ToDegrees Rad}
     Rad * 180. / PI
  end

  Radians = PI / 4.
  Degrees = 45.
in
  for F in [Sin Cos Tan] do
     {System.showInfo {F Radians}#"  "#{F {FromDegrees Degrees}}}
  end

  for I#F in [Asin#Sin Acos#Cos Atan#Tan] do
     {System.showInfo {I {F Radians}}#"  "#{ToDegrees {I {F Radians}}}}
  end


cos(Pi/2)
sin(Pi/2)
tan(Pi/2)
acos(1)
asin(1)
atan(1)


Program TrigonometricFuntions(output);

uses
  math;

var
  radians, degree: double;

begin
  radians := pi / 4.0;
  degree := 45;
  //  Pascal works in radians.  Necessary degree-radian conversions are shown.
  writeln (sin(radians),'   ', sin(degree/180*pi));
  writeln (cos(radians),'   ', cos(degree/180*pi));
  writeln (tan(radians),'   ', tan(degree/180*pi));
  writeln ();
  writeln (arcsin(sin(radians)),' Rad., or ', arcsin(sin(degree/180*pi))/pi*180,' Deg.');
  writeln (arccos(cos(radians)),' Rad., or ', arccos(cos(degree/180*pi))/pi*180,' Deg.');
  writeln (arctan(tan(radians)),' Rad., or ', arctan(tan(degree/180*pi))/pi*180,' Deg.');
  //  ( radians ) / pi * 180 = deg.
end.


use Math::Trig;

my $angle_degrees = 45;
my $angle_radians = pi / 4;

print sin($angle_radians), ' ', sin(deg2rad($angle_degrees)), "\n";
print cos($angle_radians), ' ', cos(deg2rad($angle_degrees)), "\n";
print tan($angle_radians), ' ', tan(deg2rad($angle_degrees)), "\n";
print cot($angle_radians), ' ', cot(deg2rad($angle_degrees)), "\n";
my $asin = asin(sin($angle_radians));
print $asin, ' ', rad2deg($asin), "\n";
my $acos = acos(cos($angle_radians));
print $acos, ' ', rad2deg($acos), "\n";
my $atan = atan(tan($angle_radians));
print $atan, ' ', rad2deg($atan), "\n";
my $acot = acot(cot($angle_radians));
print $acot, ' ', rad2deg($acot), "\n";


$radians = M_PI / 4;
$degrees = 45 * M_PI / 180;
echo sin($radians) . " " . sin($degrees);
echo cos($radians) . " " . cos($degrees);
echo tan($radians) . " " . tan($degrees);
echo asin(sin($radians)) . " " . asin(sin($radians)) * 180 / M_PI;
echo acos(cos($radians)) . " " . acos(cos($radians)) * 180 / M_PI;
echo atan(tan($radians)) . " " . atan(tan($radians)) * 180 / M_PI;


(load "@lib/math.l")

(de dtor (Deg)
   (*/ Deg pi 180.0) )

(de rtod (Rad)
   (*/ Rad 180.0 pi) )

(prinl
   (format (sin (/ pi 4)) *Scl) " " (format (sin (dtor 45.0)) *Scl) )
(prinl
   (format (cos (/ pi 4)) *Scl) " " (format (cos (dtor 45.0)) *Scl) )
(prinl
   (format (tan (/ pi 4)) *Scl) " " (format (tan (dtor 45.0)) *Scl) )
(prinl
   (format (asin (sin (/ pi 4))) *Scl) " " (format (rtod (asin (sin (dtor 45.0)))) *Scl) )
(prinl
   (format (acos (cos (/ pi 4))) *Scl) " " (format (rtod (acos (cos (dtor 45.0)))) *Scl) )
(prinl
   (format (atan (tan (/ pi 4))) *Scl) " " (format (rtod (atan (tan (dtor 45.0)))) *Scl) )


declare (x, xd, y, v) float;

x = 0.5; xd = 45;

/* angle in radians: */
v = sin(x); y = asin(v); put skip list (y);
v = cos(x); y = acos(v); put skip list (y);
v = tan(x); y = atan(v); put skip list (y);

/* angle in degrees: */
v = sind(xd); put skip list (v);
v = cosd(xd); put skip list (v);
v = tand(xd); y = atand(v); put skip list (y);

/* hyperbolic functions: */
v = sinh(x); put skip list (v);
v = cosh(x); put skip list (v);
v = tanh(x); y = atanh(v); put skip list (y);


DECLARE
  pi NUMBER := 4 * ATAN(1);
  radians NUMBER := pi / 4;
  degrees NUMBER := 45.0;
BEGIN
  DBMS_OUTPUT.put_line(SIN(radians) || ' ' || SIN(degrees * pi/180) );
  DBMS_OUTPUT.put_line(COS(radians) || ' ' || COS(degrees * pi/180) );
  DBMS_OUTPUT.put_line(TAN(radians) || ' ' || TAN(degrees * pi/180) );
  DBMS_OUTPUT.put_line(ASIN(SIN(radians)) || ' ' || ASIN(SIN(degrees * pi/180)) * 180/pi);
  DBMS_OUTPUT.put_line(ACOS(COS(radians)) || ' ' || ACOS(COS(degrees * pi/180)) * 180/pi);
  DBMS_OUTPUT.put_line(ATAN(TAN(radians)) || ' ' || ATAN(TAN(degrees * pi/180)) * 180/pi);
END;


90 sin =

60 cos =

%tan of 45 degrees

45 sin 45 cos div =

%inverse tan ( arc tan of sqrt 3)

3 sqrt 1 atan =


OpenConsole()

Macro DegToRad(deg)
  deg*#PI/180
EndMacro
Macro RadToDeg(rad)
  rad*180/#PI
EndMacro

degree    = 45
radians.f = #PI/4

PrintN(StrF(Sin(DegToRad(degree)))+" "+StrF(Sin(radians)))
PrintN(StrF(Cos(DegToRad(degree)))+" "+StrF(Cos(radians)))
PrintN(StrF(Tan(DegToRad(degree)))+" "+StrF(Tan(radians)))

arcsin.f = ASin(Sin(radians))
PrintN(StrF(arcsin)+" "+Str(RadToDeg(arcsin)))
arccos.f = ACos(Cos(radians))
PrintN(StrF(arccos)+" "+Str(RadToDeg(arccos)))
arctan.f = ATan(Tan(radians))
PrintN(StrF(arctan)+" "+Str(RadToDeg(arctan)))

Input()


Python 3.2.2 (default, Sep  4 2011, 09:51:08) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> from math import degrees, radians, sin, cos, tan, asin, acos, atan, pi
>>> rad, deg = pi/4, 45.0
>>> print("Sine:", sin(rad), sin(radians(deg)))
Sine: 0.7071067811865475 0.7071067811865475
>>> print("Cosine:", cos(rad), cos(radians(deg)))
Cosine: 0.7071067811865476 0.7071067811865476
>>> print("Tangent:", tan(rad), tan(radians(deg)))
Tangent: 0.9999999999999999 0.9999999999999999
>>> arcsine = asin(sin(rad))
>>> print("Arcsine:", arcsine, degrees(arcsine))
Arcsine: 0.7853981633974482 44.99999999999999
>>> arccosine = acos(cos(rad))
>>> print("Arccosine:", arccosine, degrees(arccosine))
Arccosine: 0.7853981633974483 45.0
>>> arctangent = atan(tan(rad))
>>> print("Arctangent:", arctangent, degrees(arctangent))
Arctangent: 0.7853981633974483 45.0
>>>


deg <- function(radians) 180*radians/pi
rad <- function(degrees) degrees*pi/180
sind <- function(ang) sin(rad(ang))
cosd <- function(ang) cos(rad(ang))
tand <- function(ang) tan(rad(ang))
asind <- function(v) deg(asin(v))
acosd <- function(v) deg(acos(v))
atand <- function(v) deg(atan(v))

r <- pi/3
rd <- deg(r)

print( c( sin(r), sind(rd)) )
print( c( cos(r), cosd(rd)) )
print( c( tan(r), tand(rd)) )

S <- sin(pi/4)
C <- cos(pi/3)
T <- tan(pi/4)

print( c( asin(S), asind(S) ) )
print( c( acos(C), acosd(C) ) )
print( c( atan(T), atand(T) ) )


#lang racket
(define radians (/ pi 4))
(define degrees 45)

(displayln (format "~a ~a" (sin radians) (sin (* degrees (/ pi 180)))))

(displayln (format "~a ~a" (cos radians) (cos (* degrees (/ pi 180)))))

(displayln (format "~a ~a" (tan radians) (tan (* degrees (/ pi 180)))))

(define arcsin (asin (sin radians)))
(displayln (format "~a ~a" arcsin (* arcsin (/ 180 pi))))

(define arccos (acos (cos radians)))
(displayln (format "~a ~a" arccos (* arccos (/ 180 pi))))

(define arctan (atan (tan radians)))
(display (format "~a ~a" arctan (* arctan (/ 180 pi))))


# 20210212 Updated Raku programming solution

sub postfix:<°>    (\ᵒ) { ᵒ × τ / 360 }

sub postfix:<㎭🡆°> (\ᶜ) { ᶜ / π × 180 }

say sin π/3 ;
say sin 60° ;

say cos π/4 ;
say cos 45° ;

say tan π/6 ;
say tan 30° ;

( asin(3.sqrt/2), acos(1/sqrt 2), atan(1/sqrt 3) )».&{ .say and .㎭🡆°.say }


$APPTYPE CONSOLE
$TYPECHECK ON

SUB pause(prompt$)
    PRINT prompt$
    DO
        SLEEP .1
    LOOP UNTIL LEN(INKEY$) > 0
END SUB

'MAIN
DEFDBL pi , radians , degrees , deg2rad
pi = 4 * ATAN(1)
deg2rad = pi / 180
radians = pi / 4
degrees = 45 * deg2rad

PRINT format$("%.6n" , SIN(radians)) + "  " + format$("%.6n" , SIN(degrees))
PRINT format$("%.6n" , COS(radians)) + "  " + format$("%.6n" , COS(degrees))
PRINT format$("%.6n" , TAN(radians)) + "  " + format$("%.6n" , TAN(degrees))

DEFDBL temp = SIN(radians)
PRINT format$("%.6n" , ASIN(temp)) + "  " + format$("%.6n" , ASIN(temp) / deg2rad)

temp = COS(radians)
PRINT format$("%.6n" , ACOS(temp)) + "  " + format$("%.6n" , ACOS(temp) / deg2rad)

temp = TAN(radians)
PRINT format$("%.6n" , ATAN(temp)) + "  " + format$("%.6n" , ATAN(temp) / deg2rad)

pause("Press any key to continue.")

END 'MAIN


rebol [
	Title: "Trigonometric Functions"
	URL: http://rosettacode.org/wiki/Trigonometric_Functions
]

radians: pi / 4  degrees: 45.0

; Unlike most languages, REBOL's trig functions work in degrees unless
; you specify differently.

print [sine/radians radians     sine degrees]
print [cosine/radians radians   cosine degrees]
print [tangent/radians radians  tangent degrees]

d2r: func [
	"Convert degrees to radians."
	d [number!] "Degrees"
][d * pi / 180]

arcsin: arcsine sine degrees
print [d2r arcsin  arcsin]

arccos: arccosine cosine degrees
print [d2r arccos  arccos]

arctan: arctangent tangent degrees
print [d2r arctan  arctan]