Subversion Repositories wimsdev

Rev

Rev 104 | Rev 472 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
104 bpr 1
// -*- coding: utf-8 -*-
10 reyssat 2
#include "chemeq.h"
3
#include <math.h>
4
#include <sstream>
104 bpr 5
#include <stdlib.h>
10 reyssat 6
 
7
atome lesatomes[] ={
8
{-1, "e"},
9
{1, "H"},
10
{2, "He"},
11
{3, "Li"},
12
{4, "Be"},
13
{5, "B"},
14
{6, "C"},
15
{7, "N"},
16
{8, "O"},
17
{9, "F"},
18
{10, "Ne"},
19
{11, "Na"},
20
{12, "Mg"},
21
{13, "Al"},
22
{14, "Si"},
23
{15, "P"},
24
{16, "S"},
25
{17, "Cl"},
26
{18, "Ar"},
27
{19, "K"},
28
{20, "Ca"},
29
{21, "Sc"},
30
{22, "Ti"},
31
{23, "V"},
32
{24, "Cr"},
33
{25, "Mn"},
34
{26, "Fe"},
35
{27, "Co"},
36
{28, "Ni"},
37
{29, "Cu"},
38
{30, "Zn"},
39
{31, "Ga"},
40
{32, "Ge"},
41
{33, "As"},
42
{34, "Se"},
43
{35, "Br"},
44
{36, "Kr"},
45
{37, "Rb"},
46
{38, "Sr"},
47
{39, "Y"},
48
{40, "Zr"},
49
{41, "Nb"},
50
{42, "Mo"},
51
{43, "Tc"},
52
{44, "Ru"},
53
{45, "Rh"},
54
{46, "Pd"},
55
{47, "Ag"},
56
{48, "Cd"},
57
{49, "In"},
58
{50, "Sn"},
59
{51, "Sb"},
60
{52, "Te"},
61
{53, "I"},
62
{54, "Xe"},
63
{55, "Cs"},
64
{56, "Ba"},
65
{57, "La"},
66
{58, "Ce"},
67
{59, "Pr"},
68
{60, "Nd"},
69
{61, "Pm"},
70
{62, "Sm"},
71
{63, "Eu"},
72
{64, "Gd"},
73
{65, "Tb"},
74
{66, "Dy"},
75
{67, "Ho"},
76
{68, "Er"},
77
{69, "Tm"},
78
{70, "Yb"},
79
{71, "Lu"},
80
{72, "Hf"},
81
{73, "Ta"},
82
{74, "W"},
83
{75, "Re"},
84
{76, "Os"},
85
{77, "Ir"},
86
{78, "Pt"},
87
{79, "Au"},
88
{80, "Hg"},
89
{81, "Tl"},
90
{82, "Pb"},
91
{83, "Bi"},
92
{84, "Po"},
93
{85, "At"},
94
{86, "Rn"},
95
{87, "Fr"},
96
{88, "Ra"},
97
{89, "Ac"},
98
{90, "Th"},
99
{91, "Pa"},
100
{92, "U"},
101
{93, "Np"},
102
{94, "Pu"},
103
{95, "Am"},
104
{96, "Cm"},
105
{97, "Bk"},
106
{98, "Cf"},
107
{99, "Es"},
108
{100, "Fm"},
109
{101, "Md"},
110
{102, "No"},
111
{103, "Lr"},
112
{104, "Rf"},
113
{105, "Db"},
114
{106, "Sg"},
115
{107, "Bh"},
116
{108, "Hs"},
117
{109, "Mt"},
118
{110, "Uun"},
119
{111, "Uuu"},
120
{112, "Uub"},
121
{113, "Uut"},
122
{114, "Uuq"},
123
{115, "Uup"},
124
{116, "Uuh"},
125
{117, "Uus"},
126
{118, "Uuo"},
127
{0,"fin"}
128
};
129
 
130
std::ostream & Compteur::operator << (std::ostream & o)const{
131
  const_iterator i=begin();
132
  while (i != end()){
133
    o << i->first << " : " << i->second;
134
    if (++i != end()) o << " ";
135
  }
136
  return o;
137
}
138
 
139
std::ostream & operator << (std::ostream & o, const Compteur & c){
140
  return c.operator << (o);
141
}
142
 
143
double AtomeListe::weight(fraction mult)const{
144
  const AtomeListe * al;
145
  double w=0.0;
104 bpr 146
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
10 reyssat 147
    w=mendelweight(symb)*nb*mult.i/mult.d;
148
  }
149
  else if (Zed==0){ /* cas d'un groupe */
150
    if (group) w+=group->weight(mult*nb);
151
  }
152
  if (suiv) w+=suiv->weight(mult);
153
  return w;
154
}
155
 
156
void AtomeListe::compte(Compteur &c, fraction mult)const{
157
  const AtomeListe * al;
104 bpr 158
  if(Zed!=0 && Zed!=-1 ){ /* cas où ce n'est pas un groupe ou un électron */
10 reyssat 159
    std::string key(symb);
160
    c[key] +=1.0*nb*mult.i/mult.d;
161
  }
162
  else if (Zed==0){ /* cas d'un groupe */
163
    if (group) group->compte(c,mult*nb);
164
  }
165
  if (suiv) suiv->compte(c,mult);
166
}
167
 
168
void AtomeListe::numerote(int n){
104 bpr 169
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 170
    no = n;
171
  }
172
  else if (Zed==0){ /* cas d'un groupe */
173
    no = n;
174
    if (group) group->numerote();
175
  }
176
  if (suiv) suiv->numerote(n+1);
177
}
178
 
179
AtomeListe * AtomeListe::triage(AtomeListe * al){
180
  AtomeListe * al1;
104 bpr 181
  if(al->Z()!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 182
    if (al->suiv){
183
      al->suiv = triage(al->suiv);
184
    }
185
    while (al->suiv && al->suiv->Zed!=0 &&
186
           strcmp(al->symbole(), al->suiv->symbole()) > 1){
187
      al1=al; al=al->suiv; al1->suiv=al->suiv; al->suiv=triage(al1);
188
    }
189
  }
190
  else{ /* cas d'un groupe */
191
     if (al->groupe()) al->groupe(triage(al->groupe()));
192
  }
193
  return al;
194
}
195
 
196
bool operator == (const AtomeListe & a1, const AtomeListe & a2){
197
  std::stringstream s1, s2;
198
  a1.printnorm(s1);
199
  a2.printnorm(s2);
104 bpr 200
  return s1.str() == s2.str();
10 reyssat 201
}
202
 
203
void AtomeListe::printcount(std::ostream & o, const fraction& n, int multiple=1) const{
104 bpr 204
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 205
    o << symb;
206
    o << ':' << n << '*' << multiple*nb;
207
  }
208
  else{ /* cas d'un groupe */
209
    if (group) group->printcount(o,n,nb);
210
  }  
211
  if (suiv) {o << ' '; suiv->printcount(o,n,multiple);}
212
}
213
 
214
void AtomeListe::printnorm(std::ostream & o) const{
215
  if (sqbr) o << "[";
104 bpr 216
  if(Zed!=0){ /* cas où ce n'est pas un groupe */
10 reyssat 217
    o << symb;
218
    if (nb!=1) o << nb;
219
  }
220
  else{ /* cas d'un groupe */
221
    o << "(";
222
    if (group) group->printnorm(o);
223
    o << ")" << nb;
224
  }  
225
  if (suiv) suiv->printnorm(o);
226
  if (sqbr) o << "]";
227
}
228
 
229
std::ostream & operator << (std::ostream & o, const AtomeListe & l){
230
  int n;
231
  const AtomeListe * al;
232
  if (l.sq()) o << "[";
233
  if(l.Z()>0 || l.Z()<-1){
234
    o << l.symbole();
235
  }
104 bpr 236
  else if (l.Z()==-1){ // cas de l'électron
10 reyssat 237
    o << "e";
238
  }
104 bpr 239
  else{                // cas des groupes parenthésés
10 reyssat 240
    o << "(";
241
    if((al=l.groupe())) o << *al;
242
    o << ")";
243
  }
244
  if((n=l.getmolecularite())>1) o << "_{" << n << "}";
245
  if((al=l.suivant())) o << *al;
246
  if (l.sq()) o << "]";
247
  return o;
248
}
249
 
104 bpr 250
const char* moltypeStr[] = { "aq", "g", "s" };
10 reyssat 251
 
252
bool operator == (const Molec & m1, const Molec & m2){
253
  return *(m1.al) == *(m2.al) && m1.ch == m2.ch;
254
}
255
 
256
const std::string Molec::signature()const{
257
  std::ostringstream o;
258
  o << liste();
259
  if (charge()){
260
    o << "^{";
261
    if(fabs(1.0*charge())!=1) o << fabs(1.0*charge());
262
    if(charge()>0) o << "+}"; else o << "-}";
263
  }
264
  if (t != aqueous) o << moltypeStr[t];
265
  return std::string (o.str());
266
}
267
 
268
bool Molec::printcount(std::ostream & o, bool first) const{
269
  if (!first) o << ", ";
270
  first=false;
271
  printnorm(o);
272
  o << '|';
273
  al-> printcount(o,nb);
274
  return first;
275
}
276
 
277
bool Molec::printelec(std::ostream & o, bool first) const{
278
  if (!first) o << ", ";
279
  first=false;
280
  printnorm(o);
281
  o << '|';
282
  o << nb << '*' << ch;
283
  return first;
284
}
285
 
286
bool Molec::printspecies(std::ostream & o, bool first) const{
287
  if (!first) o << ", ";
288
  first=false;
289
  printnorm(o);
290
  return first;
291
}
292
 
293
void Molec::printnorm(std::ostream & o)const{
294
  if (nb!=1) o << nb << " ";
295
  al-> printnorm(o);
296
  if (ch) {
297
    o << "^";
298
    if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
299
    if(ch>0) o << "+"; else o << "-";
300
  }
301
  if (!iswater()&&!iselectron()) o << "_" << moltypeStr[t];
302
}
303
 
304
void Molec::coeff( fraction f){
305
  nb.i *= f.i;
306
  nb.d *= f.d;
307
  nb.simplifie();
308
}
309
 
104 bpr 310
bool Molec::printNernst(std::ostream & o, const char * prefix){
10 reyssat 311
  switch(t){
312
  case sol : return 0;
313
  case aqueous :
314
    if (iswater() || iselectron()) return 0;
315
    o << prefix << "[" << *al;
316
    if (ch){
317
      o << "^{";
318
      if(fabs(1.0*ch)!=1) o << fabs(1.0*ch);
319
      if(ch>0) o << "+}"; else o << "-}";
320
    }
321
    if (t != aqueous) o << "_{" << moltypeStr[t] << "}";
322
    o  <<"]";
323
    if (nb!=1) {
324
      o << "^{";
325
      printNombre(o);
326
      o << "}";
327
    }
328
    return 1;
329
  case gas :
330
    o << prefix << "P_{" << *al << "}";
331
    if (nb!=1) {
332
      o << "^{";
333
      printNombre(o);
334
      o << "}";
335
    }
336
    return 1;
337
  }
338
}
339
 
340
bool Molec::iswater()const{
341
  if (t != aqueous) return 0;
342
  if (signature()==std::string("H_{2}O") ||
343
      signature()==std::string("OH_{2}")) return 1;
344
  else return 0;
345
}
346
 
347
bool Molec::iselectron()const{
348
  return (signature()==std::string("e^{-}"));
349
}
350
 
351
fraction Molec::nbelectron()const{
352
  if (iselectron()) return nb;
353
  else return fraction(0);
354
}
355
 
104 bpr 356
void Molec::add(fraction f){
357
  nb = nb+f;
358
}
359
 
360
void Molec::sub(fraction f){
361
  nb = nb-f;
362
}
363
 
10 reyssat 364
void Molec::printNombre(std::ostream & o)const{
365
  if (nb.d==1){
366
    o << nb.i << "\\,";
367
  }
368
  else {
369
    o << "\\frac{" << nb.i << "}{" << nb.d << "}\\,";
370
  }
371
}
372
 
373
std::ostream & operator << (std::ostream & o, const Molec & m){
374
  if (m.nombre() != 1) m.printNombre(o);
375
  o << m.liste();
376
  if (m.charge()){
377
    o << "^{";
378
    if(fabs(1.0*m.charge())!=1) o << fabs(1.0*m.charge());
379
    if(m.charge()>0) o << "+}"; else o << "-}";
380
  }
381
  if (m.typage() != aqueous) o << "_{" << moltypeStr[m.typage()] << "}";
382
  return o;
383
}
384
 
104 bpr 385
int Membre::findMol(const Molec * m){
386
  // returns the index of a molecule with the same atomlist if any
387
  // else returns -1.
388
  int result=-1;
389
  for(int i=0; i<size(); i++){
390
    if ((*this)[i]->eqMol(m)) result=i;
391
  }
392
  return result;
393
}
394
 
395
void Membre::addMol(const Molec * m){
396
  int i = findMol(m);
397
  if (i < 0){
398
    push_back(new Molec(*m));
399
  } else {
400
    (*this)[i]->add(m->nombre());
401
  }
402
}
403
 
404
void Membre::addMembre(const Membre * m){
405
  for(int i=0; i<m->size(); i++){
406
    addMol((*m)[i]);
407
  }
408
}
409
 
410
void Membre::eraseNull(){
411
  Membre m(*this);
412
  clear();
413
  for(int i=0; i < m.size();i++){
414
    if (m[i]->nombre().i>0) push_back(m[i]);
415
  }
416
}
417
 
10 reyssat 418
void Membre::compte(Compteur & c)const{
419
  for(int i =0; i < size(); i++){
420
    operator [] (i)->compte(c);
421
  }
422
}
423
 
424
void Membre::numerote(){
425
  for (int i=0; i < size(); i++){
426
    operator [](i)->numero(i);
427
    operator [](i)->liste().numerote();
428
  }
429
}
430
 
431
void Membre::triage(){
432
  int i,j;
433
  for (i=0; i < size(); i++){
434
    operator [](i)->triage();
435
  }
436
  for (i=0; i < size(); i++){
437
    for (j=i+1; j < size(); j++){
438
      if (operator [](i)->signature() > operator [](j)->signature()){
439
        Molec * m = operator [](i);
440
        operator [](i) = operator [](j);
441
        operator [](j) = m;
442
      }
443
    }
444
  }
445
}
446
 
447
void Membre::printcount(std::ostream & o) const{
448
  bool first=true;
449
  for(int i=0; i < size(); i++){
450
    first=operator[](i)->printcount(o,first);
451
  }
452
}
453
 
454
void Membre::printelec(std::ostream & o) const{
455
  bool first=true;
456
  for(int i=0; i < size(); i++){
457
    first=operator[](i)->printelec(o,first);
458
  }
459
}
460
 
461
void Membre::printspecies(std::ostream & o) const{
462
  bool first=true;
463
  for(int i=0; i < size(); i++){
464
    first=operator[](i)->printspecies(o,first);
465
  }
466
}
467
 
468
void Membre::printnorm(std::ostream & o) const{
469
  for(int i=0; i < size(); i++){
470
    operator[](i)->printnorm(o);
471
    if (i < size()-1) o << " + ";
472
  }
473
}
474
 
475
void Membre::printweight(std::ostream & o) const{
476
  for(int i=0; i < size(); i++){
477
    o << operator[](i)->weight();
478
    if (i < size()-1) o << " ";
479
  }
480
}
481
 
482
void Membre::coeff( fraction f){
483
  for (int i=0; i<size(); i++) operator[](i)->coeff(f);
484
}
485
 
486
int Membre::printableNernst(){
487
  int result=0;
488
  for (int i=0; i<size(); i++) {
489
    if (operator[](i)->typage() != sol &&
490
        !operator[](i)->iswater() &&
491
        !operator[](i)->iselectron()) result =1;
492
  }  
493
  return result;
494
}
495
 
496
bool Membre::redox()const{
497
  for (int i=0; i<size(); i++){
104 bpr 498
    if ((*this)[i]->iselectron()) /* c'est un électron */ return 1;
10 reyssat 499
  }
500
  return 0;
501
}
502
 
503
fraction  Membre::nbelectron()const{
504
  fraction result(0);
505
 
506
  for(int i = 0; i<size(); i++) result=result+(*this)[i]->nbelectron();
507
  return result;
508
}
509
 
510
void Membre::printNernst(std::ostream & o){
511
  bool printed = 0;
104 bpr 512
  const char * prefix="";
10 reyssat 513
  for (int i=0; i<size(); i++) {
514
    if (i>0) prefix="\\,";
515
    if (operator[](i)->printNernst(o, prefix)){
516
      printed = 1;
517
    }
518
  }
519
  if (!printed) o << "1";
520
}
521
 
522
std::ostream & operator << (std::ostream & o, const Membre & m){
523
  for(int i=0; i < m.size()-1; i++){
524
    o << *m[i] << "\\,+\\,";
525
  }
526
  o << *m[m.size()-1];
527
  return o;
528
}
529
 
530
Membre operator & (Membre & m1, Membre & m2){
531
  Membre result;
104 bpr 532
  result.printnorm(std::cout);
10 reyssat 533
  fraction min(1);
534
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
535
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
536
      if (**i == **j){
537
        Molec *m = new Molec(**i);
538
        if ((*i)->nb > (*j)->nb){
539
          min=(*j)->nb;
540
        }else{
541
          min=(*i)->nb;
542
        }
543
        m->nb=min;
544
        result.push_back(m);
545
      }
546
    }
547
  }
548
  return result;
549
}
550
 
551
Membre operator - (Membre & m1, Membre & m2){
552
  Membre result;
553
  fraction diff(1);
554
  for(Membre::iterator i = m1.begin(); i < m1.end(); i++){
555
    Molec *m = new Molec(**i);
556
    for(Membre::iterator j = m2.begin(); j < m2.end(); j++){
557
      if (**i == **j){
558
        diff=(*i)->nb - (*j)->nb;
559
        m->nb=diff;
560
      }
561
    }
562
    result.push_back(m);
563
  }
564
  return result;
565
}
566
 
104 bpr 567
bool Chemeq::valdefined()const{
568
  return val > MINVAL;
569
}
570
 
571
void Chemeq::addChemeq(const Chemeq * c){
572
  if (valdefined() && c->valdefined()){
573
    long double e1=enthalpy(), e2=c->enthalpy();
574
    fraction n1=nbelectron(), n2=c->nbelectron();
575
    long double e = e1+e2;
576
    fraction n=n1+n2;
577
    if (n.i==0) val=expl(-e/R/T0);
578
    else val=-e*n.d/n.i/Faraday;
579
  } else {
580
    val=MINVAL;
581
  }
582
  gauche->addMembre(c->gauche);
583
  droit->addMembre(c->droit);
584
  simplifie(true);
585
}
586
 
587
void Chemeq::subChemeq(const Chemeq * c){
588
  if (valdefined() && c->valdefined()){
589
    long double e1=enthalpy(), e2=c->enthalpy();
590
    fraction n1=nbelectron(), n2=c->nbelectron();
591
    long double e = e1-e2;
592
    fraction n=n1-n2;
593
    if (n.i==0) {
594
      val=expl(-e/R/T0);
595
    } else{
596
      val=-e*n.d/n.i/Faraday;
597
    }
598
  } else {
599
    val=MINVAL;
600
  }
601
  gauche->addMembre(c->droit);
602
  droit->addMembre(c->gauche);
603
  simplifie(true);
604
}
605
 
606
long double Chemeq::enthalpy() const{
607
  fraction n=nbelectron();
608
  if (redox()){
609
    return -val*n.i/n.d*Faraday;
610
  } else {
611
    return -R*T0*logl(val);
612
  }
613
}
614
 
615
void Chemeq::simplifie(bool tri=false){
616
  Membre communs(*gauche & *droit);
617
  if (communs.size()>0){
618
    Membre * g, *d;
619
    g= new Membre(*gauche - communs);
620
    d= new Membre(*droit  - communs);
621
    delete gauche;
622
    delete droit;
623
    gauche=g;
624
    droit =d;
625
  }
626
  gauche->eraseNull();
627
  droit->eraseNull();
628
  if (tri){
629
    numerote();
630
    triage();
631
  }
632
}
633
 
10 reyssat 634
void Chemeq::printnorm(std::ostream & o){
635
  gauche->printnorm(o);
636
  o << " -> ";
637
  droit->printnorm(o);
104 bpr 638
  if (val>MINVAL){
10 reyssat 639
    o << " (";
640
    if (cste!=std::string("")) o << cste << " = ";
641
    o << val;
642
    if (redox()) o << " V";
643
    o << ")";
644
  }
645
}
646
 
647
void Chemeq::printcount(std::ostream & o) const {
648
  gauche->printcount(o);
649
  o << "; ";
650
  droit->printcount(o);
651
}
652
 
653
void Chemeq::printelec(std::ostream & o) const {
654
  gauche->printelec(o);
655
  o << "; ";
656
  droit->printelec(o);
657
}
658
 
659
void Chemeq::printspecies(std::ostream & o) const {
660
  gauche->printspecies(o);
661
  o << "; ";
662
  droit->printspecies(o);
663
}
664
 
665
void Chemeq::printweight(std::ostream & o) const{
666
  gauche->printweight(o);
667
  o << " ";
668
  droit->printweight(o);
669
}
670
 
671
std::string Chemeq::equilibre(){
672
  std::ostringstream s;
673
  Compteur cpg, cpd;
674
  gauche->compte(cpg);
675
  droit->compte(cpd);
676
  if(cpg==cpd) s << "OK";
677
  else s << "ERROR " << cpg << " / " << cpd;
678
  return std::string(s.str());
679
}
680
 
681
void Chemeq::coeff1(){
682
  fraction mult = gauche->operator[](0)->nombre();
683
  mult.inverse();
684
  gauche->coeff(mult);
685
  droit->coeff(mult);
104 bpr 686
  simplifie();
110 bpr 687
  if (!redox() && valdefined()){
104 bpr 688
    val = val*mult.i/mult.d;
10 reyssat 689
  }
104 bpr 690
}
691
 
692
void Chemeq::multiply(int num, int den){
693
  fraction mult(num,den);
694
  gauche->coeff(mult);
695
  droit->coeff(mult);
696
  simplifie();
110 bpr 697
  if (!redox() && valdefined()){
10 reyssat 698
    val = val*mult.i/mult.d;
699
  }
700
}
701
 
702
bool Chemeq::redox()const{
703
  return gauche->redox() || droit->redox();
704
}
705
 
706
void Chemeq::printNernst(std::ostream & o){
707
  Membre * ga, * dr;
708
  if (!redox()){
709
    if (gauche->printableNernst()){
710
      o << "\\frac{";
711
      droit->printNernst(o);
712
      o << "}{";
713
      gauche->printNernst(o);
714
      o << "}";
715
    }
716
    else {
717
      droit->printNernst(o);
718
    }
104 bpr 719
    if (val > MINVAL) {
10 reyssat 720
      o << "\\,=\\,";
721
      if (cste!=std::string("")) o << cste << "\\,=\\,";
104 bpr 722
      o << valeur_latex();
10 reyssat 723
    }
724
    else{
725
      o << "\\,=\\,K";
726
    }
727
  }
104 bpr 728
  else{ /* c'est une réaction redox */
10 reyssat 729
    o << "E\\,=\\,";
104 bpr 730
    if (val > MINVAL) {
10 reyssat 731
      o << val;
732
    }
733
    else{
734
      o << "E_{0}";
735
    }
736
    o << "\\,+\\,\\frac{R\\,T}{";
737
    o << gauche->nbelectron()+droit->nbelectron() << "\\,F}";
738
    o << "\\log";
104 bpr 739
    if (gauche->redox()){ /* c'est une réduction */
10 reyssat 740
      ga=gauche; dr=droit;
741
    }
742
    else{ /* c'est une oxydation */
743
      ga=droit; dr=gauche;
744
    }
745
    if (dr->printableNernst()){
746
        o << "\\frac{";
747
        ga->printNernst(o);
748
        o << "}{";
749
        dr->printNernst(o);
750
        o << "}";
751
      }
752
      else {
753
        o << "(";
754
        ga->printNernst(o);
755
        o << ")";
756
      }
757
  }
758
}
759
 
104 bpr 760
std::string Chemeq::valeur_latex()const{
761
  std::ostringstream so;
762
  so << val;
763
  std::string s(so.str());
764
  std::string::size_type epos=s.find('e',0);
765
  if (epos!=std::string::npos){
766
    s.erase(epos,1);
767
    s.insert(epos,"\\times 10^{");
768
    s=s+"}";
769
  }
770
  return (std::string) s;
771
}
772
 
10 reyssat 773
std::ostream & operator << (std::ostream & o, const Chemeq & c){
774
  o << *c.membregauche() << "\\,\\rightarrow\\," << *c.membredroit();
104 bpr 775
  if (c.valeur() > MINVAL) {
10 reyssat 776
    o << "\\,(";
777
    if (c.constante()!=std::string("")) o << c.constante() << "\\,=\\,";
104 bpr 778
    o << c.valeur_latex();
10 reyssat 779
    if (c.redox()) o << " V";
780
    o << ")";
781
  }
782
  return o;
783
}
784
 
785
std::ostream & operator << (std::ostream & o, fraction f){
786
  o << f.i;
787
  if (f.d!=1) o << '/' << f.d;
788
  return o;
789
}
790
 
791
fraction operator * (fraction f, int m){
792
  fraction result = fraction(f.i*m, f.d);
793
  result.simplifie();
794
  return result;
795
}
796
 
797
fraction operator * (int m, fraction f){
798
  fraction result = fraction(f.i*m, f.d);
799
  result.simplifie();
800
  return result;
801
}
802
 
803
fraction operator * (fraction f, fraction m)
804
{
805
  fraction result = fraction(f.i*m.i, f.d*m.d);
806
  result.simplifie();
807
  return result;
808
}
809
 
810
fraction operator + (fraction f, fraction g){
811
  fraction result = fraction(f.i*g.d+g.i*f.d, f.d*g.d);
812
  result.simplifie();
813
  return result;
814
}
815
 
816
fraction operator - (fraction f, fraction g){
817
  fraction result = fraction(f.i*g.d-g.i*f.d, f.d*g.d);
818
  result.simplifie();
819
  return result;
820
}
821
 
104 bpr 822
const fraction & minFraction(const fraction& f1, const fraction &f2){
823
  if (f1.i*f2.d > f2.i*f1.d) return f1;
824
  else return f2;
825
}
826
 
10 reyssat 827
void fraction::simplifie(){
828
  int maxprem = 23;
829
  int premiers[]={2,3,5,7,11,13,17,19,23,29};
830
  int n;
831
 
832
  for (n=0; premiers[n]<= maxprem; n++){
833
    while (i % premiers[n] == 0 && d % premiers[n] == 0){
834
      i /= premiers[n]; d /= premiers[n];
835
    }
836
  }
837
}
838
 
839
bool operator > (fraction f, int i){
840
  return f.i > f.d*i;
841
}
842
 
843
bool operator > (fraction f1, fraction f2){
844
  return f1.i*f2.d > f1.d*f2.i;
845
}
846
 
847
bool operator != (fraction f, int i){
848
  return f.i != f.d*i;
849
}
850
 
851
double mendelweight(int i){
852
  if (i>=0) return strtod (table[i].info[WEIGHT],0); else return 0.0;
853
}
854
 
855
int findmendel(const char * symb){
856
  int i=0;
857
  while (table[i].info[0] && strcmp(table[i].info[SYMBOL], symb) != 0) i++;
858
  if (table[i].info[0]) return i; else return -1;
859
}
860
 
861
double mendelweight(const char * symb){
862
  int i;
863
  i = findmendel(symb);
864
  return mendelweight(i);
865
}