KiCad PCB EDA Suite
sim_value.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 Mikolaj Wielgus
5 * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * https://www.gnu.org/licenses/gpl-3.0.html
20 * or you may search the http://www.gnu.org website for the version 3 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <sim/sim_value.h>
26#include <wx/translation.h>
27#include <ki_exception.h>
28#include <locale_io.h>
29#include <pegtl/contrib/parse_tree.hpp>
30#include <fmt/core.h>
31
32
33#define CALL_INSTANCE( ValueType, Notation, func, ... ) \
34 switch( ValueType ) \
35 { \
36 case SIM_VALUE::TYPE_INT: \
37 switch( Notation ) \
38 { \
39 case NOTATION::SI: \
40 func<SIM_VALUE::TYPE_INT, NOTATION::SI>( __VA_ARGS__ ); \
41 break; \
42 \
43 case NOTATION::SPICE: \
44 func<SIM_VALUE::TYPE_INT, NOTATION::SPICE>( __VA_ARGS__ ); \
45 break; \
46 } \
47 break; \
48 \
49 case SIM_VALUE::TYPE_FLOAT: \
50 switch( Notation ) \
51 { \
52 case NOTATION::SI: \
53 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>( __VA_ARGS__ ); \
54 break; \
55 \
56 case NOTATION::SPICE: \
57 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SPICE>( __VA_ARGS__ ); \
58 break; \
59 } \
60 break; \
61 \
62 case SIM_VALUE::TYPE_BOOL: \
63 case SIM_VALUE::TYPE_COMPLEX: \
64 case SIM_VALUE::TYPE_STRING: \
65 case SIM_VALUE::TYPE_BOOL_VECTOR: \
66 case SIM_VALUE::TYPE_INT_VECTOR: \
67 case SIM_VALUE::TYPE_FLOAT_VECTOR: \
68 case SIM_VALUE::TYPE_COMPLEX_VECTOR: \
69 wxFAIL_MSG( "Unhandled SIM_VALUE type" ); \
70 break; \
71 }
72
73
75{
76 using namespace SIM_VALUE_GRAMMAR;
77
78 template <typename Rule>
79 struct numberSelector : std::false_type {};
80
81 // TODO: Reorder. NOTATION should be before TYPE.
82
83 template <> struct numberSelector<SIM_VALUE_GRAMMAR::significand<SIM_VALUE::TYPE_INT>>
84 : std::true_type {};
85 template <> struct numberSelector<SIM_VALUE_GRAMMAR::significand<SIM_VALUE::TYPE_FLOAT>>
86 : std::true_type {};
87 template <> struct numberSelector<intPart> : std::true_type {};
88 template <> struct numberSelector<fracPart> : std::true_type {};
89 template <> struct numberSelector<exponent> : std::true_type {};
90 template <> struct numberSelector<metricSuffix<SIM_VALUE::TYPE_INT, NOTATION::SI>>
91 : std::true_type {};
92 template <> struct numberSelector<metricSuffix<SIM_VALUE::TYPE_INT, NOTATION::SPICE>>
93 : std::true_type {};
94 template <> struct numberSelector<metricSuffix<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>>
95 : std::true_type {};
96 template <> struct numberSelector<metricSuffix<SIM_VALUE::TYPE_FLOAT, NOTATION::SPICE>>
97 : std::true_type {};
98
100 {
101 bool isOk = true;
102 bool isEmpty = true;
103 std::string significand;
104 std::optional<int64_t> intPart;
105 std::optional<int64_t> fracPart;
106 std::optional<int> exponent;
107 std::optional<int> metricSuffixExponent;
108 };
109
110 PARSE_RESULT Parse( const std::string& aString,
111 NOTATION aNotation = NOTATION::SI,
113
114 int MetricSuffixToExponent( std::string aMetricSuffix, NOTATION aNotation = NOTATION::SI );
115 std::string ExponentToMetricSuffix( double aExponent, int& aReductionExponent,
116 NOTATION aNotation = NOTATION::SI );
117 }
118
119
120template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
121static inline void doIsValid( tao::pegtl::string_input<>& aIn )
122{
123 tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn );
124}
125
126
127bool SIM_VALUE_GRAMMAR::IsValid( const std::string& aString,
128 SIM_VALUE::TYPE aValueType,
129 NOTATION aNotation )
130{
131 tao::pegtl::string_input<> in( aString, "from_content" );
132
133 try
134 {
135 CALL_INSTANCE( aValueType, aNotation, doIsValid, in );
136 }
137 catch( const tao::pegtl::parse_error& )
138 {
139 return false;
140 }
141
142 return true;
143}
144
145
146template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
147static inline std::unique_ptr<tao::pegtl::parse_tree::node> doParse(
148 tao::pegtl::string_input<>& aIn )
149{
150 return tao::pegtl::parse_tree::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>,
152 ( aIn );
153}
154
155
156template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
157static inline void handleNodeForParse( tao::pegtl::parse_tree::node& aNode,
158 SIM_VALUE_PARSER::PARSE_RESULT& aParseResult )
159{
160 if( aNode.is_type<SIM_VALUE_PARSER::significand<ValueType>>() )
161 {
162 aParseResult.significand = aNode.string();
163 aParseResult.isEmpty = false;
164
165 for( const auto& subnode : aNode.children )
166 {
167 if( subnode->is_type<SIM_VALUE_PARSER::intPart>() )
168 aParseResult.intPart = std::stol( subnode->string() );
169 else if( subnode->is_type<SIM_VALUE_PARSER::fracPart>() )
170 aParseResult.fracPart = std::stol( subnode->string() );
171 }
172 }
173 else if( aNode.is_type<SIM_VALUE_PARSER::exponent>() )
174 {
175 aParseResult.exponent = std::stoi( aNode.string() );
176 aParseResult.isEmpty = false;
177 }
179 {
180 aParseResult.metricSuffixExponent =
181 SIM_VALUE_PARSER::MetricSuffixToExponent( aNode.string(), Notation );
182 aParseResult.isEmpty = false;
183 }
184 else
185 wxFAIL_MSG( "Unhandled parse tree node" );
186}
187
188
190 NOTATION aNotation,
191 SIM_VALUE::TYPE aValueType )
192{
193 LOCALE_IO toggle;
194
195 tao::pegtl::string_input<> in( aString, "from_content" );
196 std::unique_ptr<tao::pegtl::parse_tree::node> root;
197 PARSE_RESULT result;
198
199 try
200 {
201 CALL_INSTANCE( aValueType, aNotation, root = doParse, in );
202 }
203 catch( tao::pegtl::parse_error& )
204 {
205 result.isOk = false;
206 return result;
207 }
208
209 wxASSERT( root );
210
211 try
212 {
213 for( const auto& node : root->children )
214 {
215 CALL_INSTANCE( aValueType, aNotation, handleNodeForParse, *node, result );
216 }
217 }
218 catch( const std::invalid_argument& e )
219 {
220 wxFAIL_MSG( fmt::format( "Parsing simulator value failed: {:s}", e.what() ) );
221 result.isOk = false;
222 }
223
224 return result;
225}
226
227
228int SIM_VALUE_PARSER::MetricSuffixToExponent( std::string aMetricSuffix, NOTATION aNotation )
229{
230 switch( aNotation )
231 {
232 case NOTATION::SI:
233 if( aMetricSuffix.empty() )
234 return 0;
235
236 switch( aMetricSuffix[0] )
237 {
238 case 'a': return -18;
239 case 'f': return -15;
240 case 'p': return -12;
241 case 'n': return -9;
242 case 'u': return -6;
243 case 'm': return -3;
244 case 'k':
245 case 'K': return 3;
246 case 'M': return 6;
247 case 'G': return 9;
248 case 'T': return 12;
249 case 'P': return 15;
250 case 'E': return 18;
251 }
252
253 break;
254
255 case NOTATION::SPICE:
256 std::transform( aMetricSuffix.begin(), aMetricSuffix.end(), aMetricSuffix.begin(),
257 ::tolower );
258
259 if( aMetricSuffix == "f" )
260 return -15;
261 else if( aMetricSuffix == "p" )
262 return -12;
263 else if( aMetricSuffix == "n" )
264 return -9;
265 else if( aMetricSuffix == "u" )
266 return -6;
267 else if( aMetricSuffix == "m" )
268 return -3;
269 else if( aMetricSuffix == "" )
270 return 0;
271 else if( aMetricSuffix == "k" )
272 return 3;
273 else if( aMetricSuffix == "meg" )
274 return 6;
275 else if( aMetricSuffix == "g" )
276 return 9;
277 else if( aMetricSuffix == "t" )
278 return 12;
279
280 break;
281 }
282
283 wxFAIL_MSG( fmt::format( "Unknown simulator value suffix: '{:s}'", aMetricSuffix ) );
284 return 0;
285}
286
287
288std::string SIM_VALUE_PARSER::ExponentToMetricSuffix( double aExponent, int& aReductionExponent,
289 NOTATION aNotation )
290{
291 if( aNotation == NOTATION::SI && aExponent >= -18 && aExponent <= -15 )
292 {
293 aReductionExponent = -18;
294 return "a";
295 }
296 else if( aExponent >= -15 && aExponent < -12 )
297 {
298 aReductionExponent = -15;
299 return "f";
300 }
301 else if( aExponent >= -12 && aExponent < -9 )
302 {
303 aReductionExponent = -12;
304 return "p";
305 }
306 else if( aExponent >= -9 && aExponent < -6 )
307 {
308 aReductionExponent = -9;
309 return "n";
310 }
311 else if( aExponent >= -6 && aExponent < -3 )
312 {
313 aReductionExponent = -6;
314 return "u";
315 }
316 else if( aExponent >= -3 && aExponent < 0 )
317 {
318 aReductionExponent = -3;
319 return "m";
320 }
321 else if( aExponent >= 0 && aExponent < 3 )
322 {
323 aReductionExponent = 0;
324 return "";
325 }
326 else if( aExponent >= 3 && aExponent < 6 )
327 {
328 aReductionExponent = 3;
329 return "k";
330 }
331 else if( aExponent >= 6 && aExponent < 9 )
332 {
333 aReductionExponent = 6;
334 return ( aNotation == NOTATION::SI ) ? "M" : "Meg";
335 }
336 else if( aExponent >= 9 && aExponent < 12 )
337 {
338 aReductionExponent = 9;
339 return "G";
340 }
341 else if( aExponent >= 12 && aExponent < 15 )
342 {
343 aReductionExponent = 12;
344 return "T";
345 }
346 else if( aNotation == NOTATION::SI && aExponent >= 15 && aExponent < 18 )
347 {
348 aReductionExponent = 15;
349 return "P";
350 }
351 else if( aNotation == NOTATION::SI && aExponent >= 18 && aExponent <= 21 )
352 {
353 aReductionExponent = 18;
354 return "E";
355 }
356
357 aReductionExponent = 0;
358 return "";
359}
360
361
362std::unique_ptr<SIM_VALUE> SIM_VALUE::Create( TYPE aType, std::string aString )
363{
364 std::unique_ptr<SIM_VALUE> value = SIM_VALUE::Create( aType );
365 value->FromString( aString );
366 return value;
367}
368
369
370std::unique_ptr<SIM_VALUE> SIM_VALUE::Create( TYPE aType )
371{
372 switch( aType )
373 {
374 case TYPE_BOOL: return std::make_unique<SIM_VALUE_BOOL>();
375 case TYPE_INT: return std::make_unique<SIM_VALUE_INT>();
376 case TYPE_FLOAT: return std::make_unique<SIM_VALUE_FLOAT>();
377 case TYPE_COMPLEX: return std::make_unique<SIM_VALUE_COMPLEX>();
378 case TYPE_STRING: return std::make_unique<SIM_VALUE_STRING>();
379 case TYPE_BOOL_VECTOR: return std::make_unique<SIM_VALUE_BOOL>();
380 case TYPE_INT_VECTOR: return std::make_unique<SIM_VALUE_INT>();
381 case TYPE_FLOAT_VECTOR: return std::make_unique<SIM_VALUE_FLOAT>();
382 case TYPE_COMPLEX_VECTOR: return std::make_unique<SIM_VALUE_COMPLEX>();
383 }
384
385 wxFAIL_MSG( _( "Unknown SIM_VALUE type" ) );
386 return nullptr;
387}
388
389
390void SIM_VALUE::operator=( const std::string& aString )
391{
392 FromString( aString );
393}
394
395
396bool SIM_VALUE::operator!=( const SIM_VALUE& aOther ) const
397{
398 return !( *this == aOther );
399}
400
401
402template <typename T>
403SIM_VALUE_INST<T>::SIM_VALUE_INST( const T& aValue ) : m_value( aValue )
404{
405}
406
407template SIM_VALUE_BOOL::SIM_VALUE_INST( const bool& aValue );
408template SIM_VALUE_INT::SIM_VALUE_INST( const int& aValue );
409template SIM_VALUE_FLOAT::SIM_VALUE_INST( const double& aValue );
410template SIM_VALUE_COMPLEX::SIM_VALUE_INST( const std::complex<double>& aValue );
411template SIM_VALUE_STRING::SIM_VALUE_INST( const std::string& aValue );
412
413
414template <typename T>
416{
417 return m_value.has_value();
418}
419
420
421template <>
422bool SIM_VALUE_BOOL::FromString( const std::string& aString, NOTATION aNotation )
423{
424 SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
425 m_value = std::nullopt;
426
427 if( !parseResult.isOk )
428 return false;
429
430 if( parseResult.isEmpty )
431 return true;
432
433 if( !parseResult.intPart
434 || ( *parseResult.intPart != 0 && *parseResult.intPart != 1 )
435 || parseResult.fracPart
436 || parseResult.exponent
437 || parseResult.metricSuffixExponent )
438 {
439 return false;
440 }
441
442 m_value = *parseResult.intPart;
443 return true;
444}
445
446
447template <>
448bool SIM_VALUE_INT::FromString( const std::string& aString, NOTATION aNotation )
449{
450 SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
451 m_value = std::nullopt;
452
453 if( !parseResult.isOk )
454 return false;
455
456 if( parseResult.isEmpty )
457 return true;
458
459 if( !parseResult.intPart || ( parseResult.fracPart && *parseResult.fracPart != 0 ) )
460 return false;
461
462 int exponent = parseResult.exponent ? *parseResult.exponent : 0;
463 exponent += parseResult.metricSuffixExponent ? *parseResult.metricSuffixExponent : 0;
464
465 m_value = static_cast<double>( *parseResult.intPart ) * std::pow( 10, exponent );
466 return true;
467}
468
469
470template <>
471bool SIM_VALUE_FLOAT::FromString( const std::string& aString, NOTATION aNotation )
472{
473 SIM_VALUE_PARSER::PARSE_RESULT parseResult = SIM_VALUE_PARSER::Parse( aString, aNotation );
474 m_value = std::nullopt;
475
476 if( !parseResult.isOk )
477 return false;
478
479 if( parseResult.isEmpty )
480 return true;
481
482 // Single dot should be allowed in fields.
483 // TODO: disallow single dot in models.
484 if( parseResult.significand.empty() || parseResult.significand == "." )
485 return false;
486
487 int exponent = parseResult.exponent ? *parseResult.exponent : 0;
488 exponent += parseResult.metricSuffixExponent ? *parseResult.metricSuffixExponent : 0;
489
490 try
491 {
492 m_value = std::stod( parseResult.significand ) * std::pow( 10, exponent );
493 }
494 catch( const std::invalid_argument& )
495 {
496 return false;
497 }
498
499 return true;
500}
501
502
503template <>
504bool SIM_VALUE_COMPLEX::FromString( const std::string& aString,
505 NOTATION aNotation )
506{
507 // TODO
508
509 /*LOCALE_IO toggle;
510
511 double value = 0;
512
513 if( !aString.ToDouble( &value ) )
514 throw KI_PARAM_ERROR( _( "Invalid complex sim value string" ) );
515
516 m_value = value;*/
517 return true;
518}
519
520
521template <>
522bool SIM_VALUE_STRING::FromString( const std::string& aString, NOTATION aNotation )
523{
524 m_value = aString;
525 return true;
526}
527
528
529template <typename T>
530std::string SIM_VALUE_INST<T>::ToString( NOTATION aNotation ) const
531{
532 static_assert( std::is_same<T, std::vector<T>>::value );
533
534 std::string string = "";
535
536 for( auto it = m_value.cbegin(); it != m_value.cend(); it++ )
537 {
538 string += SIM_VALUE_INST<T>( *it ).ToString();
539 string += ",";
540 }
541
542 return string;
543}
544
545
546template <>
547std::string SIM_VALUE_BOOL::ToString( NOTATION aNotation ) const
548{
549 if( m_value )
550 return fmt::format( "{:d}", *m_value );
551
552 return "";
553}
554
555
556template <>
557std::string SIM_VALUE_INT::ToString( NOTATION aNotation ) const
558{
559 if( m_value )
560 {
561 int value = std::abs( *m_value );
562 int exponent = 0;
563
564 while( value != 0 && value % 1000 == 0 )
565 {
566 exponent += 3;
567 value /= 1000;
568 }
569
570 int dummy = 0;
572 static_cast<double>( exponent ), dummy, aNotation );
573 return fmt::format( "{:d}{:s}", value, metricSuffix );
574 }
575
576 return "";
577}
578
579
580template <>
581std::string SIM_VALUE_FLOAT::ToString( NOTATION aNotation ) const
582{
583 if( m_value )
584 {
585 double exponent = std::log10( std::abs( *m_value ) );
586 int reductionExponent = 0;
587
588 std::string metricSuffix =
589 SIM_VALUE_PARSER::ExponentToMetricSuffix( exponent, reductionExponent, aNotation );
590 double reducedValue = *m_value / std::pow( 10, reductionExponent );
591
592 return fmt::format( "{:g}{}", reducedValue, metricSuffix );
593 }
594 else
595 return "";
596}
597
598
599template <>
600std::string SIM_VALUE_COMPLEX::ToString( NOTATION aNotation ) const
601{
602 if( m_value )
603 return fmt::format( "{:g}+{:g}i", m_value->real(), m_value->imag() );
604
605 return "";
606}
607
608
609template <>
610std::string SIM_VALUE_STRING::ToString( NOTATION aNotation ) const
611{
612 if( m_value )
613 return *m_value;
614
615 return ""; // Empty string is completely equivalent to null string.
616}
617
618
619template <typename T>
621{
622 if( m_value )
623 return fmt::format( "{}", *m_value );
624
625 return "";
626}
627
628
629template <>
630std::string SIM_VALUE_COMPLEX::ToSimpleString() const
631{
632 // TODO
633
634 /*std::string result = "";
635 result << *m_value;
636
637 return result;*/
638 return "";
639}
640
641
642template <typename T>
643bool SIM_VALUE_INST<T>::operator==( const T& aOther ) const
644{
645 return m_value == aOther;
646}
647
648
649template <>
650bool SIM_VALUE_BOOL::operator==( const bool& aOther ) const
651{
652 // Note that we take nullopt as the same as false here.
653
654 if( !m_value )
655 return false == aOther;
656
657 return m_value == aOther;
658}
659
660
661template bool SIM_VALUE_INT::operator==( const int& aOther ) const;
662template bool SIM_VALUE_FLOAT::operator==( const double& aOther ) const;
663template bool SIM_VALUE_COMPLEX::operator==( const std::complex<double>& aOther ) const;
664template bool SIM_VALUE_STRING::operator==( const std::string& aOther ) const;
665
666
667template <typename T>
668bool SIM_VALUE_INST<T>::operator==( const SIM_VALUE& aOther ) const
669{
670 const SIM_VALUE_INST<T>* otherValue = dynamic_cast<const SIM_VALUE_INST<T>*>( &aOther );
671
672 if( otherValue )
673 return m_value == otherValue->m_value;
674
675 return false;
676}
677
678template <typename T>
680{
681 return SIM_VALUE_INST( aLeft.m_value.value() + aRight.m_value.value() );
682}
683
684template SIM_VALUE_INT operator+( const SIM_VALUE_INT& aLeft,
685 const SIM_VALUE_INT& aRight );
687 const SIM_VALUE_FLOAT& aRight );
688
689
690template <typename T>
692{
693 return SIM_VALUE_INST( aLeft.m_value.value() - aRight.m_value.value() );
694}
695
696template SIM_VALUE_INT operator-( const SIM_VALUE_INT& aLeft,
697 const SIM_VALUE_INT& aRight );
699 const SIM_VALUE_FLOAT& aRight );
700
701
702 template <typename T>
704{
705 return SIM_VALUE_INST( aLeft.m_value.value() * aRight.m_value.value() );
706}
707
708template SIM_VALUE_INT operator*( const SIM_VALUE_INT& aLeft,
709 const SIM_VALUE_INT& aRight );
711 const SIM_VALUE_FLOAT& aRight );
712
713 template <typename T>
715{
716 return SIM_VALUE_INST( aLeft.m_value.value() / aRight.m_value.value() );
717}
718
719template SIM_VALUE_INT operator/( const SIM_VALUE_INT& aLeft,
720 const SIM_VALUE_INT& aRight );
722 const SIM_VALUE_FLOAT& aRight );
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
std::optional< T > m_value
Definition: sim_value.h:128
bool operator==(const T &aOther) const
Definition: sim_value.cpp:643
std::string ToString(NOTATION aNotation=NOTATION::SI) const override
Definition: sim_value.cpp:530
bool FromString(const std::string &aString, NOTATION aNotation=NOTATION::SI) override
Definition: sim_value.cpp:422
std::string ToSimpleString() const override
Definition: sim_value.cpp:620
bool HasValue() const override
Definition: sim_value.cpp:415
SIM_VALUE_INST()=default
void operator=(const std::string &aString)
Definition: sim_value.cpp:390
static std::unique_ptr< SIM_VALUE > Create(TYPE aType, std::string aString)
Definition: sim_value.cpp:362
@ TYPE_BOOL
Definition: sim_value.h:56
@ TYPE_FLOAT_VECTOR
Definition: sim_value.h:64
@ TYPE_BOOL_VECTOR
Definition: sim_value.h:62
@ TYPE_INT
Definition: sim_value.h:57
@ TYPE_FLOAT
Definition: sim_value.h:58
@ TYPE_INT_VECTOR
Definition: sim_value.h:63
@ TYPE_COMPLEX_VECTOR
Definition: sim_value.h:65
@ TYPE_STRING
Definition: sim_value.h:60
@ TYPE_COMPLEX
Definition: sim_value.h:59
bool operator!=(const SIM_VALUE &aOther) const
Definition: sim_value.cpp:396
virtual bool FromString(const std::string &aString, NOTATION aNotation=NOTATION::SI)=0
#define _(s)
bool IsValid(const std::string &aString, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT, NOTATION aNotation=NOTATION::SI)
Definition: sim_value.cpp:127
PARSE_RESULT Parse(const std::string &aString, NOTATION aNotation=NOTATION::SI, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT)
Definition: sim_value.cpp:189
std::string ExponentToMetricSuffix(double aExponent, int &aReductionExponent, NOTATION aNotation=NOTATION::SI)
Definition: sim_value.cpp:288
int MetricSuffixToExponent(std::string aMetricSuffix, NOTATION aNotation=NOTATION::SI)
Definition: sim_value.cpp:228
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
SIM_VALUE_INST< T > operator/(const SIM_VALUE_INST< T > &aLeft, const SIM_VALUE_INST< T > &aRight)
Definition: sim_value.cpp:714
SIM_VALUE_INST< T > operator+(const SIM_VALUE_INST< T > &aLeft, const SIM_VALUE_INST< T > &aRight)
Definition: sim_value.cpp:679
SIM_VALUE_INST< T > operator-(const SIM_VALUE_INST< T > &aLeft, const SIM_VALUE_INST< T > &aRight)
Definition: sim_value.cpp:691
SIM_VALUE_INST< T > operator*(const SIM_VALUE_INST< T > &aLeft, const SIM_VALUE_INST< T > &aRight)
Definition: sim_value.cpp:703
static void handleNodeForParse(tao::pegtl::parse_tree::node &aNode, SIM_VALUE_PARSER::PARSE_RESULT &aParseResult)
Definition: sim_value.cpp:157
static std::unique_ptr< tao::pegtl::parse_tree::node > doParse(tao::pegtl::string_input<> &aIn)
Definition: sim_value.cpp:147
#define CALL_INSTANCE(ValueType, Notation, func,...)
Definition: sim_value.cpp:33
static void doIsValid(tao::pegtl::string_input<> &aIn)
Definition: sim_value.cpp:121
std::optional< int64_t > fracPart
Definition: sim_value.cpp:105
std::optional< int > metricSuffixExponent
Definition: sim_value.cpp:107
std::optional< int > exponent
Definition: sim_value.cpp:106
std::optional< int64_t > intPart
Definition: sim_value.cpp:104