#!/bin/bash
# Tämä on skriptiajurin skripti ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/matemaattiset_funktiot, mutta siä voi käyttää yksinäänkin käskyllä: . /home/petteri/OMATSKRIPTIT/FUNKTIOKIRJASTO/matemaattiset_funktiot      
# lyhyen kuvauksen toiminnasta saa käskyllä: laske .  petteriIII 10.6.2016 http://forum.ubuntu-fi.org/index.php?topic=47408.msg364003#top. 

# matemaattisten funktioiden toiminta on seuraava: niin kauan kuin laskussa on sulkuja tehdään korkeimman tason sulun sisällöstä rekursiivinen kutsu. Etsitään tässä uudessa laskussa olevat funktiot ja niiden argumentit, ratkaistaan funktiot ja korvataan funktiot argumentteineen saadulla arvolla. Kun funktioita ei ole enempää niin lähetetään peruslaskutoimituksista muodostuva loppu bc:lle joka antaa sille numeroarvon, palataan rekursiosta ja korvataan alkuperäisessä laskussa sulku siitä saadulla arvolla. Kun sulkuja ei enää ole etsitään jäljelle jääneestä laskusta siinä olevat funktiot argumentteineen ja korvataan funktiot argumentteineen saadulla arvolla. Kun funktioitakaan ei enää ole niin lähetetään lasku jossa on jäljellä vain peruslaskutoimituksia bc:n ratkaistavaksi. 

# Ei ole aina ilmanmuuta selvää onko kysymys peruslaskutoimituksesta vai funktiosta. Esimerkiksi bc:n kannalta kokonaislukupotenssi on nopea ja tarkka peruslaskutoimitus mutta desimaalipotenssi on funktio joka on hieman hitaampi ja virheellisempi joten kun molempia aloitetaan käsitelellä funktiona ja kun tämä skripti  valitsee automaattisesti oikean tavan joten aina toimitaan parhaalla mahdollisella tavalla.

# Skriptin rakenne ei ole seväpiirteinen eikä senvuoksi kommentointiakaan ole paljoa. Vaan kannattaa ottaa kaikki vain esimerkkinä siitä mihin BASH kykenee. Toiminnan parsiminen on kuitenkin mahdollista.

# ulkoinen laskuohjelma ei saa olettaa mitään, ei rajoittaa mitään ja on oltava valmis määräämään täysin naurettavatkin asiat sillä muuten ne voivat periä arvonsa jostain muualta. Matematiikan sääntöjä on noudatettava mahdollisimman orjallisesti.

# ulkoinen laskuohjelma ei saa myöskään olettaa mitään sisääntulon mielekkyydestä vaan kaikkeen ihmeellisyyteen on varauduttava. Esimerkiksi merkintä -0. on hyväksyttävä nollaksi ja -- on hyväksyttävä plussaksi.

# vastauksessa on lopussa lopputolos numerona kahdella viimeisellä "rivillä". Toiseksiviimeinen on tämän skiptin antama tulos. Viimeinen numero on se vastaus johon se "koulussa" pyöristettäisiin. Kertomia ei ole pyöristetty sillä ne ovat aina kokonaislukuja sillä desimaalikertomien kaavaa ei tässä skriptissä ole. Myöskään imaginaarisia arvoja ei käsitellä.

set +H # jos tämä puuttuisi niin kertoman merkki: ! aiheuttaisi virheen paitsi viimeisenä merkkinä
unset command_not_found_handle # poistaa huomautukset mallia: tarkoititko käskyä xxx paketissa yyy
export BC_LINE_LENGTH=0 # jotta bc tulostaisi koko tulosteen yhtenä pötkönä; elikä ilman kenoja
# 2> /dev/null # uudelleensuuntaa virhetulostuksen 
 
trap 'laske "$BASH_COMMAND"' 1 ERR 

function laske () { # Tuloparametrina on laskukaava. Tulostaa näytölle ja asettaa kutsuttujen funktioiden nimiset muuttujat ja tuloksen muuttujaan: tulos.
stty sane # <ctrl+j>stty sane<ctrl+j> # echo <ctrl-v><esc>c<enter> # reset # palauttaa päätteen järkiinsä
[[ ! "$1" ]] && echo "- Niin tämä kuin kaikki muutkin BASH-skriptit toimivat ainoastaan päätteessä (terminal). Pääte oppii matematiikkaa kun päätteesssä oltaessa siinä annetaan käsky(piste kuuluu käskyyn): . polku/matemaattiset_funktiot
- siis päätteeseen voi silloin kirjoittaa esimerkiksi: 1+1  ja kun painaa return niin näytölle tulee: 2. Tai tuossa päätteessä toimivaan skriptiin voidaan kirjoittaa: x=1+1 (tai mikä lasku tahansa) mikäli skriptin alussa on tuo liitoskäsky.
- mikäli antaa ratkaistavaksi matemaattisen mahdottomuuden alkaa näyttö sekoilla. Silloin on viisainta sulkea se pääte ja avata uusi.
- nämä ohjeet kirjoitetaan näytölle käskyllä: laske
- BASH:in virheviesteistä tulee vaikeaselkoisempia. Vanhan toiminnan saa palautettua lopettamalla päätteen jossa tämä matematiikka toimii ja avaamalla uuden päätteen. 
- laskuissa on 66 desimaalia jollei toisin määrätä. Desimaalipisteen jälkeisen osan peränollia ei tulosteta.
- kokonaisosan numeromäärä on aina rajoittamaton ja desimaalien määrän voi määrätä ihan miksi haluaa laskun etuliitteellä desxxxx . 
- laskun desimaalien määrä vaikuttaa joskus lopputulokseen paljonkin vaikka harvoin ratkaisevasti. Tällä ohjelmalla asiasta saa pätevän käsityksen.
- sallitut operaattorit: +, -, *, / ja ^ Näissä laskuissa ^ on potenssiinkorotus, esimerkiksi 3^0.5.
- laskut lasketaan sieventämättä. Tulos on siten luotettavampi mikäli matematiikkamoottori (tässä bc) osaa laskun suorittaa. Tulokset tosin saadaan paljon hitaammin. 
- desimaalien ja radiaanien määräämis-esimerkki: des256radsin0.511 . Käskyt voidaan jakaa eri riveillekin:
des256 return rad return sin0.511. Asetukset ovat voimassa niinkauan kunnes määrätään uudestaan
- käsky stat kertoo muutaman tilastotiedon laskusta
 
- funktiot: sin, asin, sinh, cos, acos, cosh, tan, atan, tanh, sqrt, log, ln, exp, abs, int, e, pi, ! (=kertoma), aa (10 järjestelmästä 2 järjestelmään), bb (2 järjestelmästä 10 järjestelmään), des(desimaalien määrä laskussa), deg, rad ja stat. Ja teoriassa uusien funktioiden lisääminen on helppoa.
- merkitätavat noudattavat normaaleja matematiikan sääntöjä. Sulkuina on kuitenkin käytettävä hakasulkuja. 
- syötettävien lukujen esitysmuoto voi olla tieteellinenkin, esimerkiksi: 1.23e6. Ohjelma osaa erottaa koska e tarkoittaa luonnollisen lukujärjestelmän kantalukua e.

testilaskuja toimiminnan oikeellisuuden toteamiseksi:
-1*log.001-[[2*6!+1]/1.441e3]+[[sin210-cos60]*tan60*2]/[3^.5]*ln[e^-pi]/pi-e^[2*ln2] -> 0
des256ln[e^ln[e^ln[e^ln[e^ln[e^ln[e^ln[e^ln[e^-pi]]]]]]]]+pi -> 0;  
2+1.1e2+e-2.7 -> 112.018....
des256[6^-6^6.1^6^-5.9^6^6]-[6^-6^6.1^6^-5.9^6^6] -> 0. 
[sin30]^2+[cos30]^2-1 -> 0 (merkintä yleensä sin²30+cos²30=1) 
sin[30^2]+cos[30^2]-1 -> -2
10001!/10002!-1/10002 -> 0
1.1^2.1-e^[2.1*ln1.1] -> 0
des1200aa[[2^999-1]/2^999] -> .<ja tuhat ykköstä>
[sin[asin.1]]-asin[sin.1]+[atan[tan.1]]-tan[atan.1] -> 0 sekä deg etta rad
- muuttujakin voidaan ratkaista: x=0.5; sin \$x
- edellisen laskun tulokseen käänteisluku tulostuu kun antaa laskuksi pelkän 1:n" && return 


[[ "$1" = "stat" ]] && echo -n 'kokonaisosan numeromäärä: ' && echo $tulos | wc -c && echo -n 'lasku kesti sekunneissa: ' && bc <<< $loppuhetki-$alkuhetki && return
alkuhetki=$(date +%s.%N)
[[ "$1" = 1 ]] && tulos='1/'$tulos || tulos="$1"
[[ $(tr -dc '\[' <<<"$tulos" | awk '{ print length; }') -ne $(tr -dc '\]' <<<"$tulos" | awk '{ print length; }') ]] && echo 'sulut epätasapainossa' && return
[[ -z $sulkujaratkaisematta ]] && {
sulkujaratkaisematta=1
 
lasketaan_radiaaneissa=${lasketaan_radiaaneissa:-0} # toimintaan asteissa ellei toimintamuodoksi peritä radiaaneja.
desimaaleja=$(echo $tulos | grep -Po '(?<=des)[0-9]*' ) && tulos=${tulos//des$desimaaleja}
desimaaleja=${desimaaleja:-66} # laskujen desimaaliluku on 66 ellei peritä toista arvoa.
desimaaleja=$((desimaaleja+5)) # koelisäys

tulos=${tulos#+}    # poistetaan laskun edestä merkki + jos sellainen on
tulos=${tulos%% #*} # poistetaan peräkommentit - peräkommentin edessä on aina välilyönti
tulos=$(echo $tulos | tr -d \' | tr '(' '[' | tr ')' ']' ) # poistetaan heittomerkki ja muunnetaan kaarisulut hakasuluiksi.
tulos=${tulos//++/+}; tulos=${tulos//\*+/\*}; tulos=${tulos//\/+/\/}; tulos=${tulos//\^+/\^}; tulos=${tulos//\*\*/\^};


[[ $(echo $tulos | grep rad) ]] && lasketaan_radiaaneissa=1 && tulos=${tulos//rad} 
[[ $(echo $tulos | grep deg) ]] && lasketaan_radiaaneissa=0 && tulos=${tulos//deg} 

# muutetaan luonnollisen järjestelmän kantaluku e lukuarvoonsa kaikkialla. Siis luvut kuten tuo e kaavassa: 1+e^2
e_numeroina=$(echo "scale=$desimaaleja; e(1)" | bc -l)
tulos=$(echo $tulos | sed "s/\be\b/$e_numeroina/g")
# muutetaan pi (ympyrän kehä/halkaisija) lukuarvoonsa kaikkialla
pi_numeroina=$(echo "scale=$desimaaleja; 4*a(1)" | bc -l) # koe - oli: scale=256
tulos=$(echo $tulos | sed "s/\bpi\b/$pi_numeroina/g") 
} # vastaava alku-sulku on rivillä 43 elikä rivillä jolla on teksti: [[ -z sulkujaratkaisematta ]] && {

# muuta kaikki tieteelliset esitysmuodot numeroiksi heti kun "eksponentti" on ratkaistu (niinkuin: 1.23e5 -> 123000)
muuta_tieteelliset_esitystykset_numeroiksi

tput cuu1; tput el; echo # kursori ylös rivinverran ja rivin tyhjennys
[[ $(echo $tulos | grep "/[+-\'']0") ]] && echo "jako nollalla, epämääräinen tulos" && return

etsi_laskukaavasta_ratkaisukelpoinen_sulku_ja_ratkaise_se

for funktiolaji in $(echo $tulos | tr [0-9/*+-^] " " ); do 
 erota_sulun_seuraavasta_funktiosta_parametrit_ja_kutsu_funktiota $funktiolaji ; done

# ratkaise x^y kaikkialla missä x ja y on ratkaistu numeroiksi; siis sulut ratkottu
apu=$(echo $tulos | grep -o [0-9.][0-9.]*^[0-9.+-][0-9.]*) # | tr "\n" " " | awk '{print $1}')
while [[  $apu != "" ]] ; do ratkaise_eksponentti $apu; apu=$(echo $tulos | grep -o [0-9.][0-9.]*^[0-9.+-][0-9.]*); done
# mikä on seuraavan lauseen merkitys ? Laskee tuloksen silloin kun jäljellä on enää numeroita?
[[ $(echo $tulos | tr -d \.[0-9]) ]] && tulos=${tulos//--/+} && tulos=$(echo "obase=10;ibase=10;scale=$desimaaleja ; $tulos" | bc -l) && [[ $vanha_tulos != $tulos ]] &&  tulosta $tulos && vanha_tulos=$tulos
[[ "${#FUNCNAME[@]}" = 1 ]] && unset vanha_tulos && unset sulkujaratkaisematta && siisti_lopputulos # viimeisellä kierroksella funktio-pinossa on yksi jäsen ja tulos voidaan pyöristää
# trap '' 1 ERR
}

function siisti_lopputulos () { # pyöristys oikealla tavalla,tarkkuuden palautus #ja desimaaliosan peränollien poisto 
loppuhetki=$(date +%s.%N)
# [[ "$1" = "stat" ]] && echo -n 'exponentti edellisestä laskusta: ' && echo $(echo $tulos | cut -d. -f1) | wc -c; 
echo

desimaaleja=$((desimaaleja-5)) # tarkkuuden palautus
#kokonaisosa=$(echo $tulos | cut -d. -f1)                                # koe alkaa
#desimaaliosa=$(echo $tulos | cut -d. -f2 | cut -c -$(($desimaaleja+1))) # koe
#tulos=$konaisosa$desimaaliosa                                           # koe loppuu    
[[ ${tulos:0:1} == "-" ]] && miinusalussa=1 || miinusalussa=0 
[[ $funktiolaji == ! ]] && echo $tulos | bc | cut -d. -f1 | sed 's/^$/0/g;s/^-$/0/g' && return # kertoma on aina kokonaisluku joten sitä ei pyöristetä
bc <<< "scale=$((desimaaleja+1));$tulos+(-1*$miinusalussa)*5*10^-$((desimaaleja+1))" | cut -c -$((desimaaleja+$(expr index "$tulos" .))) | sed 's/0*$//g;s/\.$//g' | sed 's/^$/0/g;s/^-$/0/g' # desimaalilukujen pyöristys oikealla tavalla, turhien peränollien poistaminen desimaaliosan perästä ja luvun perässä olevan yksinäisen desimaalipisteenkin poistaminen ja vaihtamalla tyhjä tulos nollaksi ja muuttamalla pelkkä miinusmerkki nollaksi
# tulos=RESULT # taitaa olla turha ? 
}

function erota_sulun_seuraavasta_funktiosta_parametrit_ja_kutsu_funktiota () {
[[ ! $(declare | grep $funktiolaji' \(\)') ]] && echo tuntematon funktio && return
[[ $funktiolaji = ! ]] && apu=$(echo ${tulos%%\!*}  | sed 's/\^/ /g;s/\*/ /g;s/\// /g;s/\+/ /g;s/\-/ /g') && numero=${apu##* }
[[ $funktiolaji != ! ]] && apu=$(echo ${tulos#*$funktiolaji} | sed  's/\^/ /g;s/\*/ /g;s/\// /g;s/\+/ /g;s/\-/ /g') && numero=${apu%% *}
[[ $numero = "" ]] && apuu=$(echo ${tulos#*$funktiolaji}) && apu=${apuu:0:1}${apu:1} && numero=${apu%% *} # palautetaan operaattoreita poistettaessa hävinnyt merkki
kutsu="$funktiolaji $numero"; arvo=$($kutsu); korvattava=$funktiolaji$numero;[[ $funktiolaji = ! ]] && korvattava=$numero$funktiolaji;tulos=$(echo $tulos | sed "s/$korvattava/$arvo/g")
}

function tulosta () { #  mikäli luvussa on desimaalipiste niin poistetaan peränollat ja pistekin jos se jää loppuun yksikseen
vanha_tulos=$1; [[ $vanha_tulos != $1 ]] && return
[[ ${1%%\.*} != $1 ]] && echo $1 | sed 's/0*$//g;s/\.$//g' || echo $1  # peränollien poisto ja desimaalipisteen poisto tarvittaessa
}

function ratkaise_eksponentti () { # kokonais-exsponenteille bc käyttää tarkkaa eksponentaatiota mutta se ei hyväksy desimaalisia exponentteja. Tässä desimaaliexponentit ohjataan käyttämään niille soveltuvaa hieman hitaanpaa ja epätarkempaa desimaali-eksponentiaatiota.
kantaluku=${1%%^*} 
exponentti=${1##*^}
[[ $(echo $exponentti | grep "\." ) ]] && valitulos=$(echo "scale=$desimaaleja; e($exponentti*l($kantaluku))" | bc -l) || valitulos=$(echo "scale=$desimaaleja; $kantaluku^$exponentti" | bc -l)
# valitulos=$(echo $valitulos | cut -b 1-$desimaaleja) # tämä rivi on lisätty 
korvattava=$kantaluku"\^"$exponentti; tulos=${tulos//$korvattava/$valitulos}   
tulosta $tulos
}
 
function etsi_laskukaavasta_ratkaisukelpoinen_sulku_ja_ratkaise_se  () {
# raja=112\101\116\116\101\114\105\73\73\73
while [[ $tulos != $(echo $tulos | tr -d []) ]]; do
ilman_sulkuja=$(echo $tulos | sed 's/\].*//g;s/.*\[//g') # tämä lause etsii ratkaisukelpoisen sulun
apu=$(echo $tulos | grep -Fob -- $ilman_sulkuja)
monennestako_merkista=${apu%%\:*}
monenteenko_merkkiin=$(echo $monennestako_merkista+${#ilman_sulkuja} | bc )
tulosta $tulos
tulos_alussa="$tulos" 
tulos=$(echo $tulos | tr -d []) 
laske $ilman_sulkuja
tulos=${tulos_alussa:0:$monennestako_merkista-1}$tulos${tulos_alussa:$monenteenko_merkkiin+1}; echo $tulos
# muuta_tieteelliset_esitystykset_numeroiksi # tarvitaanko tässäkohtaa?
done
}

function muuta_tieteelliset_esitystykset_numeroiksi() { # ratkaistaan tieteellinen esitystapa; luvut mallia 1.23e18
apu=$(echo $tulos | grep -o  [.0-9]*e[.0-9+-]* | tr "\n" " " | tr -d '" "\\' | awk '{print $1}')
while [[ $apu ]] ; do arvo=$(echo $apu | sed "s/e/\*10\^/g" | bc -l); tulos=${tulos//$apu/$arvo} ; apu=$(echo $tulos | grep -o  [.0-9]*e[0-9+-]* | tr -d "\\\n" | tr -d '' | awk '{print $1}'); done 
}

function tan () {
asteluku=$(echo ${1#+}) # jos asteluvun edessä on + niin  poistetaan se
[[ $lasketaan_radiaaneissa -eq 1 ]] && tan=$(echo "scale=$desimaaleja; s($asteluku)/c($asteluku)" | bc -l ) || tan=$(echo "scale=$desimaaleja; s($asteluku*$pi_numeroina/180)/c($asteluku*$pi_numeroina/180)" | bc -l)  ; tulosta $tan 
}

function aa () { # Lukumuunnos kymmenjärjestelmästä kaksijärjestelmään. Toimii myös desimaaliluvuille. Käännettävällä luvulla voi olla etumerkkikin. Muunnoksen suorittaa matematiikkaohjelma bc joka onkin kokonaisluvuille ihanteellinen. On se ihateellinen desimaaliluvuillekin, mutta sille täytyy desimaalilukujen kyseessä ollen antaa joskus lisämääreitä. 

# Lukujärjestemämuunnoksissa täytyy alkaa ajatella esitystarkkuuksia sillä jos esimerkiksi kymmenjärjestelmässä esitetään luku jonka tarkkuus olisi 66 desimaalia niin siitä saatetaan desimaalipisteen perässä esittää vain jotain pientä koska peränollia ei kirjoiteta. Lisäksi kaksijärjestelmässä sama tarkkuus  kuin mihin kymmenjärjestelmässä vaatii 66 desimaalia saavutetaan kaksijärjestelmässä luvulla jossa on noin 4*66 elikä 264:llä desimaalia. Ja tähän täytyy lisätä kokonaisosan merkkimäärä.

# bc-ohjelman pitää saada tämä tarkkuustieto toisella tavalla kuin normaalisti. Sitä normaalia scale-käskyä ei ole ollenkaan vaan sensijaan muunnettavan desimaaliluvun perään liitetään niin monta nollaa kuin käännetyssä luvussa saattaisi olla.

# Otetaanpa esimerkiksi luku 1234567890123456789012345678901234567890123456789012345678901234567890.24 ja tehdään sille käännöskäsky: des264aa123456789012----.24 . Tulosteessa on karmea joukko ykkös-nollaa. Huomioi desimaalipiste - voit käsitellä sen kummallakin puolella olevaa lukua itsenäisesti.

# muunnoksen oikeellisuuden tarkistamiskäsky tässä tapauksessa on: des66bb<se luku joka saatiin käskystä des264aa123456789012---.24> . Vastauksena pitää tulla:123456789012---.24 66-desimaalin tarkkuudella - viimeinen numero voi tosin olla yhdellä väärin sillä pyöristyksessä on tällähetkellä jotakin häikkää.

# tarkistamiseen voi käyttää myös käskyjä joissa tietää jo etukäteen mitä tuloksen pitää olla, esimerkiksi: des264aa[[2^99]-1/2^99] tyyppisiä  - tässä tapauksessa .<ja 100 ykköstä>
 
# ja lopuksi kaksirivinen käsky bc:lle:
# [[ $(echo $1 | tr -cd . ) ]] && apu=$1$(printf "%0"$desimaaleja"d\n") || apu=$1 
aa=$(echo "scale=$desimaaleja;ibase=10;obase=2;$apu" | bc -l) ; tulosta $aa
}

function bb () { # muunnos kaksijärjestelmästä kymmenjärjestelmään. Sopii myös desimaaliluvuille. Käännettävällä luvulla voi olla etumerkkikin.
# mitään kummallisuuksia ei koskaan tule sillä käännettävä luku kertoo bc:lle kaiken tarpeellisen.
bb=$(echo "scale=$((2*$desimaaleja));obase=10;ibase=2;$1" | bc -l) ; tulosta $bb
}

function cos () {
asteluku=$(echo ${1#+}) # jos asteluvun edessä on + niin  poistetaan se
[[ $lasketaan_radiaaneissa -eq 1 ]] && cos=$(echo "scale=$desimaaleja; c($asteluku)" | bc -l) || cos=$(echo "scale=$desimaaleja; c($asteluku*$pi_numeroina/180)" | bc -l) ; tulosta $cos
}

function log () { # briggsin logaritmi
[[ $(echo $1 | sed 's/0*$//g;s/\.$//g') == 1 ]] && log=0 || log=$(echo "scale=$desimaaleja; l($1)/l(10)" | bc -l); tulosta $log;
}

function ln () { # e-kantainen logaritmi
[[ $(echo $1 | sed 's/0*$//g ;s/\.$//g') == 1 ]] && ln=0 ||
ln=$(echo "scale=$desimaaleja; l($1)" | bc -l); tulosta $ln 
}

function sqrt () { # neliöjuuri
[[ $(echo $1 | tr -cd - ) ]] && exit
sqrt=$(echo "scale=$desimaaleja; sqrt($1)" | bc -l); tulosta $sqrt
}

function ! () {
[[ $1 -eq 0 ]] && kertoma=1 || kertoma=$(seq -s* $1 | bc | tr -d '\\\n'); tulosta $kertoma
}

function atan () { # arctan
[[ $lasketaan_radiaaneissa -eq 1 ]] && atan=$(echo "scale=$desimaaleja; a($1)" | bc -l) || atan=$(echo "scale=$desimaaleja; a($1)*180/$pi_numeroina" | bc -l) ; tulosta $atan
}

function sin () {
asteluku=$(echo ${1#+}) # jos asteluvun edessä on + niin  poistetaan se
[[ $lasketaan_radiaaneissa -eq 1 ]] && sin=$(echo "scale=${desimaaleja:-66}; s($asteluku)" | bc -l) || sin=$(echo "scale=${desimaaleja:-66}; s($asteluku*$pi_numeroina/180)" | bc -l); tulosta $sin # miksei tulos saa uutta arvoa ?
}

function acos () { # arccos # lasku on: pi/2-asin, rajuja muutoksia
viesti='acos on määritelty vain välillä -1...+1. otetaan arvoksi:'
[[ $(echo $1 '>=' 1 | bc -l) -eq 1 ]] && acos=0 && echo -n $viesti && tulota $acos && return
[[ $(echo $1 '<=' -1 | bc -l) -eq 1 ]] && acos=1 && echo -n $viesti && tulosta $acos && return
[[ $lasketaan_radiaaneissa -eq 1 ]] && acos=$(echo "scale=${desimaaleja:-66}; $pi_numeroina/2-a($apu/sqrt(1-($1*$1)))" | bc -l) || acos=$(echo "scale=${desimaaleja:-66}; 180/$pi_numeroina*($pi_numeroina/2-a($1/sqrt(1-($1*$1))))" | bc -l) 
tulosta $acos
}

function asin () { # arcsini, rajuja muutoksia
viesti='asin on määritelty vain välillä -1...+1. otetaan arvoksi:'
[[ $(echo $1 '>=' 1 | bc -l) -eq 1 ]] && acos=0 && echo -n $viesti && tulosta $acos && return
[[ $(echo $1 '<=' -1 | bc -l) -eq 1 ]] && acos=1 && echo -n $viesti && tulosta $acos && return
[[ $lasketaan_radiaaneissa -eq 1 ]] && asin=$(echo "scale=${desimaaleja:-66}; a($1/sqrt(1-($1*$1)))" | bc -l) || asin=$(echo "scale=${desimaaleja:-66}; a($1/sqrt(1-($1*$1)))*180/$pi_numeroina" | bc -l) 
tulosta $asin
}

function sinh () { # korvauskaava on: ( e^x - e^-x )/2
sinh=$(echo "scale=${desimaaleja:-66}; ($e_numeroina^$1-$e_numeroina^-$1)/2" | bc -l);tulosta $sinh
}

function cosh () { # korvauskaava on: ( e^x + e^-x )/2
cosh=$(echo "scale=${desimaaleja:-66}; ($e_numeroina^$1+$e_numeroina^-$1)/2" | bc -l) ; tulosta $cosh
}

function tanh () { # korvauskaava on: ( e^x - e^-x )/( e^x + e^-x )
tanh=$(echo "scale=${desimaaleja:-66};  ($e_numeroina^$1-$e_numeroina^-$1)/($e_numeroina^$1+$e_numeroina^-$1)" | bc -l) ; tulosta $tanh
}

function abs () { # tämä poistaa etumerkin, myös plussan
abs=$1; abs=$(echo ${abs#[-+]}); tulosta $abs
}

function int () { # muuttujan kokonaisluku-osa
[[ ${1:0:1} != \. ]] && int=$(echo $1 | cut -d. -f1 ) || int=0;  tulosta $int | sed 's/[+-]0/0/g;s/^-$/0/g'
}
 



   



