123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200(*
* BatComplex - Extended Complex Numbers
* Copyright (C) 2007 Bluestorm <bluestorm dot dylc on-the-server gmail dot com>
* 2008 David Teller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)moduleBaseComplex=structincludeComplexletmodulo__=failwith"BatComplex.modulo is meaningless"letto_stringx=(string_of_floatx.re)^" + i "^(string_of_float x.im)letpredx={xwithre=x.re-.1.}letsuccx={xwithre=x.re+.1.}letto_intx=int_of_floatx.reletof_intx={re=float_of_intx;im=0.}letto_float x=x.reletof_floatx={re=x;im=0.}letabsx={re=normx;im=0.}letcomparet1t2=matchcomparet1.ret2.rewith|0-> comparet1.imt2.im|c->cletord=BatOrd.ordcompareletequalt1t2=t1.re=t2.re&&t1.im=t2.imletof_stringx=letfails=failwith(Printf.sprintf"BatComplex.of_string %S: %s" xs)inletopenGenlexinletenum=BatGenlex.to_enum_filter(BatGenlex.of_list [".";"i";"+";"-";"*"])(BatString.enumx)inletrecparse_re ()=matchBatEnum.peekenumwith|None->fail"the string is empty"|Some(Inti)->BatEnum.junkenum;parse_separation(float_of_inti)|Some(Floatf)->BatEnum.junkenum;parse_separationf|Some(Kwd"-")->BatEnum.junkenum;parse_i_im~multiplier:(-1.)0.|Some(Kwd"+")->BatEnum.junkenum;parse_i_im~multiplier:1.0.|Some_token->parse_i_im~multiplier:1.0.andparse_separationre=matchBatEnum.get enumwith|None->{re;im=0.}|Some(Kwd"-")->parse_i_im~multiplier:(-1.)re|Some(Kwd"+")->parse_i_im~multiplier:1.re|Some_->fail"unexpected token after real part"andparse_i_im~multiplierre=matchBatEnum.get enumwith|Some(Kwd"i")->(matchBatEnum.peekenumwith|None -> {re;im=multiplier}|Some(Kwd".")|Some(Kwd"*")->BatEnum.junkenum;parse_im ~multiplierre|Some_token->parse_im~multiplierre)|_->fail"expected \"i\" before the imaginary part"andparse_im~multiplierre=matchBatEnum.peek enumwith|Some(Inti)->BatEnum.junkenum;parse_end{re;im=multiplier *.float_of_inti}|Some(Floatf)->BatEnum.junkenum;parse_end{re;im=multiplier *.f}|_->fail"expected a number for the imaginary part"andparse_endc=matchBatEnum.peekenumwith|None->c|Some_->fail"unexpected trailing tokens"inparse_re()end(* need to fix problem with Functor return type being `type t =
Complex.t` and needing `type t = Complex.t = {re: float; im:float}` *)moduleCN=BatNumber.MakeNumeric(BaseComplex)includeBaseComplexletoperations=CN.operationsmoduleInfix=BatNumber.MakeInfix(BaseComplex)includeInfixmoduleCompare =BatNumber.MakeCompare(BaseComplex)letinv=Complex.invleti=Complex.iletconj=Complex.conjletsqrt=Complex.sqrtletnorm2=Complex.norm2letnorm=Complex.normletarg=Complex.argletpolar =Complex.polarletexp=Complex.expletlog =Complex.logletpow =Complex.powletprintoutt=BatInnerIO.nwrite out(to_stringt)(*$T succ
succ{re = 2.; im = 4.} = {re = 3.; im = 4.}
*)(*$T pred
pred {re = 2.; im = 4.} = {re = 1.; im = 4.}
*)(*$T abs
abs {re = 3.; im = 4.} = {re = 5.; im = 0.}
*)(*$T to_int
to_int {re = 2.; im = 3.} = 2
*)(*$T of_int
of_int 2 = {re = 2.; im = 0.}
*)(*$T to_float
to_float {re = 2.; im = 3.} = 2.
*)(*$T of_float
of_float 2. = {re = 2.; im = 0.}
*)(*$T compare
compare {re = 2.; im = 3.} {re = 2.; im = 3.} = 0
compare {re = 2.; im = 3.} {re = 3.; im = 2.} = -1
compare {re = 3.; im = 3.} {re = 2.; im = 3.} = 1
compare {re = 3.; im = 4.} {re = 3.; im = 3.} = 1
compare {re = 3.; im = -4.} {re = 3.; im = 3.} = -1
*)(*$T equal
equal {re = 2.; im = 3.} {re = 2.; im = 3.}
not (equal {re = 2.; im = 3.} {re = 3.; im = 2.})
not (equal {re = 3.; im = 3.} {re = 2.; im = 3.})
not (equal {re = 3.; im = 4.} {re = 3.; im = 3.})
*)(*$T of_string
of_string "1." = of_float 1.
of_string "-1." = {re = -1.; im = 0.}
of_string "1 + i 2." = {re = 1.; im = 2.}
of_string "1 - i 2." = {re = 1.; im = -2.}
of_string "1 - i 2e3" = {re = 1.; im = -2e3}
of_string "-1. - i -2e3" = {re = -1.; im = 2e3}
of_string "-1+i 2e3" = {re = -1.; im = 2e3}
of_string "-1. - i. -2e3" = {re = -1.; im = 2e3}
of_string "-1. - i * -2e3" = {re = -1.; im = 2e3}
of_string " - i * -2e3" = {re = 0.; im = 2e3}
of_string "+ i * -2e3" = {re = 0.; im = -2e3}
of_string "i * -2e3" = {re = 0.; im = -2e3}
of_string "i" = {re = 0.; im = 1.}
of_string "-i" = {re = 0.; im = -1.}
of_string "1 + i" = {re = 1.; im = 1.}
try ignore (of_string " "); false with Failure _ -> true
try ignore (of_string "("); false with BatGenlex.LexerError _ -> true
try ignore (of_string "1 +"); false with Failure _ -> true
try ignore (of_string "i +"); false with Failure _ -> true
try ignore (of_string "1 + i * 3 4"); false with Failure _ -> true
try ignore (of_string "1 2"); false with Failure _ -> true
*)(*$T print
BatIO.to_string print {re=3.4; im= -5.6} = "3.4 + i -5.6"
*)