pcbnew: Allow tuning length to be longer than INT_MAX

The INT_MAX limit for most elements makes sense only for single-segment,
straight line elements.  For elements that accumulate lengths, we should
utilize the long long int (64 bits) to allow for greater lengths.

Fixes: lp:1842367
* https://bugs.launchpad.net/kicad/+bug/1842367
This commit is contained in:
Seth Hillbrand 2019-09-03 16:38:58 -07:00
parent 8bbbc66e46
commit c8a6878eb8
17 changed files with 74 additions and 90 deletions

View File

@ -124,7 +124,14 @@ double To_User_Unit( EDA_UNITS_T aUnit, double aValue, bool aUseMils )
// A lower-precision (for readability) version of StringFromValue() // A lower-precision (for readability) version of StringFromValue()
wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils ) wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils )
{ {
return MessageTextFromValue( aUnits, (double) aValue, aUseMils ); return MessageTextFromValue( aUnits, double( aValue ), aUseMils );
}
// A lower-precision (for readability) version of StringFromValue()
wxString MessageTextFromValue( EDA_UNITS_T aUnits, long long int aValue, bool aUseMils )
{
return MessageTextFromValue( aUnits, double( aValue ), aUseMils );
} }
@ -207,7 +214,7 @@ void StripTrailingZeros( wxString& aStringValue, unsigned aTrailingZeroAllowed )
* otherwise the actual value is rounded when read from dialog and converted * otherwise the actual value is rounded when read from dialog and converted
* in internal units, and therefore modified. * in internal units, and therefore modified.
*/ */
wxString StringFromValue( EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils ) wxString StringFromValue( EDA_UNITS_T aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils )
{ {
double value_to_print = To_User_Unit( aUnits, aValue, aUseMils ); double value_to_print = To_User_Unit( aUnits, aValue, aUseMils );
@ -411,10 +418,10 @@ void FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS_T& aUnits, bool
} }
int ValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils ) long long int ValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils )
{ {
double value = DoubleValueFromString( aUnits, aTextValue, aUseMils ); double value = DoubleValueFromString( aUnits, aTextValue, aUseMils );
return KiROUND( value ); return KiROUND<double, long long int>( value );
} }

View File

@ -100,9 +100,9 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse() const
} }
int SHAPE_LINE_CHAIN::Length() const long long int SHAPE_LINE_CHAIN::Length() const
{ {
int l = 0; long long int l = 0;
for( int i = 0; i < SegmentCount(); i++ ) for( int i = 0; i < SegmentCount(); i++ )
l += CSegment( i ).Length(); l += CSegment( i ).Length();

View File

@ -123,7 +123,7 @@ void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
} }
bool UNIT_BINDER::Validate( int aMin, int aMax, bool setFocusOnError ) bool UNIT_BINDER::Validate( long long int aMin, long long int aMax, bool setFocusOnError )
{ {
auto textEntry = dynamic_cast<wxTextEntry*>( m_value ); auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
@ -212,7 +212,7 @@ void UNIT_BINDER::ChangeValue( wxString aValue )
} }
int UNIT_BINDER::GetValue() long long int UNIT_BINDER::GetValue()
{ {
auto textEntry = dynamic_cast<wxTextEntry*>( m_value ); auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
auto staticText = dynamic_cast<wxStaticText*>( m_value ); auto staticText = dynamic_cast<wxStaticText*>( m_value );

View File

@ -112,6 +112,8 @@ wxString MessageTextFromValue( EDA_UNITS_T aUnits, double aValue, bool aUseMils
wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils = false ); wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils = false );
wxString MessageTextFromValue( EDA_UNITS_T aUnits, long long int aValue, bool aUseMils = false );
/** /**
* Function StringFromValue * Function StringFromValue
* returns the string from \a aValue according to units (inch, mm ...) for display, * returns the string from \a aValue according to units (inch, mm ...) for display,
@ -132,8 +134,8 @@ wxString MessageTextFromValue( EDA_UNITS_T aUnits, int aValue, bool aUseMils = f
* @param aUseMils Indicates mils should be used for imperial units (inches). * @param aUseMils Indicates mils should be used for imperial units (inches).
* @return A wxString object containing value and optionally the symbol unit (like 2.000 mm) * @return A wxString object containing value and optionally the symbol unit (like 2.000 mm)
*/ */
wxString StringFromValue( EDA_UNITS_T aUnit, int aValue, bool aAddUnitSymbol = false, wxString StringFromValue(
bool aUseMils = false ); EDA_UNITS_T aUnit, double aValue, bool aAddUnitSymbol = false, bool aUseMils = false );
/** /**
* Return in internal units the value "val" given in a real unit * Return in internal units the value "val" given in a real unit
@ -162,7 +164,8 @@ double DoubleValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue,
* @param aUseMils Indicates mils should be used for imperial units (inches). * @param aUseMils Indicates mils should be used for imperial units (inches).
* @return The string from Value, according to units (inch, mm ...) for display, * @return The string from Value, according to units (inch, mm ...) for display,
*/ */
int ValueFromString( EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils = false ); long long int ValueFromString(
EDA_UNITS_T aUnits, const wxString& aTextValue, bool aUseMils = false );
/** /**
* Function FetchUnitsFromString * Function FetchUnitsFromString

View File

@ -43,7 +43,9 @@
#include <gal/color4d.h> #include <gal/color4d.h>
#include <atomic> #include <atomic>
#include <limits>
#include <memory> #include <memory>
#include <type_traits>
class wxAboutDialogInfo; class wxAboutDialogInfo;
class SEARCH_STACK; class SEARCH_STACK;
@ -105,49 +107,20 @@ enum pseudokeys {
/** /**
* Round a floating point number to an integer using "round halfway cases away from zero". * Round a floating point number to an integer using "round halfway cases away from zero".
* *
* In Debug build an assert fires if will not fit into an int. * In Debug build an assert fires if will not fit into the return type.
*/ */
template <typename fp_type, typename ret_type = int>
#if !defined( DEBUG ) constexpr ret_type KiROUND( fp_type v )
/// KiROUND: a function so v is not evaluated twice. Unfortunately, compiler
/// is unable to pre-compute constants using this.
static inline int KiROUND( double v )
{ {
return int( v < 0 ? v - 0.5 : v + 0.5 ); using max_ret = long long int;
fp_type ret = v < 0 ? v - 0.5 : v + 0.5;
wxASSERT( ret <= std::numeric_limits<ret_type>::max()
&& ret >= std::numeric_limits<ret_type>::lowest() );
return ret_type( max_ret( ret ) );
} }
/// KIROUND: a macro so compiler can pre-compute constants. Use this with compile
/// time constants rather than the inline function above.
#define KIROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 )
#else
// DEBUG: KiROUND() is a macro to capture line and file, then calls this inline
static inline int kiRound_( double v, int line, const char* filename )
{
v = v < 0 ? v - 0.5 : v + 0.5;
if( v > INT_MAX + 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n",
__FUNCTION__, filename, line, v );
}
else if( v < INT_MIN - 0.5 )
{
printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n",
__FUNCTION__, filename, line, v );
}
return int( v );
}
#define KiROUND( v ) kiRound_( v, __LINE__, __FILE__ )
// in Debug build, use the overflow catcher since code size is immaterial
#define KIROUND( v ) KiROUND( v )
#endif
//-----</KiROUND KIT>----------------------------------------------------------- //-----</KiROUND KIT>-----------------------------------------------------------

View File

@ -364,7 +364,7 @@ public:
* Returns length of the line chain in Euclidean metric. * Returns length of the line chain in Euclidean metric.
* @return length of the line chain * @return length of the line chain
*/ */
int Length() const; long long int Length() const;
/** /**
* Function Append() * Function Append()

View File

@ -85,7 +85,7 @@ public:
* Function GetValue * Function GetValue
* Returns the current value in Internal Units. * Returns the current value in Internal Units.
*/ */
virtual int GetValue(); virtual long long int GetValue();
/** /**
* Function IsIndeterminate * Function IsIndeterminate
@ -102,7 +102,7 @@ public:
* @param aMax a maximum value (in internal units) for validation * @param aMax a maximum value (in internal units) for validation
* @return false on error. * @return false on error.
*/ */
virtual bool Validate( int aMin, int aMax, bool setFocusOnError = true ); virtual bool Validate( long long int aMin, long long int aMax, bool setFocusOnError = true );
void SetLabel( const wxString& aLabel ); void SetLabel( const wxString& aLabel );

View File

@ -107,13 +107,13 @@ bool DIALOG_PNS_LENGTH_TUNING_SETTINGS::TransferDataToWindow()
bool DIALOG_PNS_LENGTH_TUNING_SETTINGS::AcceptOptions( ) bool DIALOG_PNS_LENGTH_TUNING_SETTINGS::AcceptOptions( )
{ {
if( !m_minAmpl.Validate( 0, INT_MAX ) ) if( !m_minAmpl.Validate( 0, std::numeric_limits<int>::max() ) )
return false; return false;
if( !m_maxAmpl.Validate( m_minAmpl.GetValue(), INT_MAX ) ) if( !m_maxAmpl.Validate( m_minAmpl.GetValue(), std::numeric_limits<int>::max() ) )
return false; return false;
if( !m_spacing.Validate( 0, INT_MAX ) ) if( !m_spacing.Validate( 0, std::numeric_limits<int>::max() ) )
return false; return false;
if( !m_targetLength.Validate( 0, INT_MAX ) ) if( !m_targetLength.Validate( 0, std::numeric_limits<long long int>::max() ) )
return false; return false;
if( !m_radius.Validate( 0, 100 ) ) if( !m_radius.Validate( 0, 100 ) )
return false; return false;

View File

@ -119,10 +119,10 @@ void DP_MEANDER_PLACER::release()
} }
int DP_MEANDER_PLACER::origPathLength() const long long int DP_MEANDER_PLACER::origPathLength() const
{ {
int totalP = 0; long long int totalP = 0;
int totalN = 0; long long int totalN = 0;
for( const ITEM* item : m_tunedPathP.CItems() ) for( const ITEM* item : m_tunedPathP.CItems() )
{ {
@ -243,7 +243,7 @@ bool DP_MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
while( curIndexN < tunedN.PointCount() ) while( curIndexN < tunedN.PointCount() )
m_result.AddCorner( tunedP.CPoint( -1 ), tunedN.CPoint( curIndexN++ ) ); m_result.AddCorner( tunedP.CPoint( -1 ), tunedN.CPoint( curIndexN++ ) );
int dpLen = origPathLength(); long long int dpLen = origPathLength();
m_lastStatus = TUNED; m_lastStatus = TUNED;

View File

@ -98,7 +98,7 @@ public:
int CurrentLayer() const override; int CurrentLayer() const override;
int totalLength(); long long int totalLength();
const wxString TuningInfo( EDA_UNITS_T aUnits ) const override; const wxString TuningInfo( EDA_UNITS_T aUnits ) const override;
TUNING_STATUS TuningStatus() const override; TUNING_STATUS TuningStatus() const override;
@ -120,7 +120,7 @@ private:
void setWorld( NODE* aWorld ); void setWorld( NODE* aWorld );
void release(); void release();
int origPathLength() const; long long int origPathLength() const;
///> pointer to world to search colliding items ///> pointer to world to search colliding items
NODE* m_world; NODE* m_world;
@ -141,7 +141,7 @@ private:
MEANDERED_LINE m_result; MEANDERED_LINE m_result;
SEGMENT* m_initialSegment; SEGMENT* m_initialSegment;
int m_lastLength; long long int m_lastLength;
TUNING_STATUS m_lastStatus; TUNING_STATUS m_lastStatus;
}; };

View File

@ -80,8 +80,8 @@ public:
int m_spacing; int m_spacing;
///> amplitude/spacing adjustment step ///> amplitude/spacing adjustment step
int m_step; int m_step;
///> desired length of the tuned line/diff pair ///> desired length of the tuned line/diff pair (this is in nm, so allow more than board width)
int m_targetLength; long long int m_targetLength;
///> type of corners for the meandered line ///> type of corners for the meandered line
MEANDER_STYLE m_cornerStyle; MEANDER_STYLE m_cornerStyle;
///> rounding percentage (0 - 100) ///> rounding percentage (0 - 100)

View File

@ -89,9 +89,9 @@ bool MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
} }
int MEANDER_PLACER::origPathLength() const long long int MEANDER_PLACER::origPathLength() const
{ {
int total = 0; long long int total = 0;
for( const ITEM* item : m_tunedPath.CItems() ) for( const ITEM* item : m_tunedPath.CItems() )
{ {
if( const LINE* l = dyn_cast<const LINE*>( item ) ) if( const LINE* l = dyn_cast<const LINE*>( item ) )
@ -110,7 +110,7 @@ bool MEANDER_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
} }
bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, int aTargetLength ) bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int aTargetLength )
{ {
SHAPE_LINE_CHAIN pre, tuned, post; SHAPE_LINE_CHAIN pre, tuned, post;
@ -133,7 +133,7 @@ bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, int aTargetLeng
m_result.AddCorner( s.B ); m_result.AddCorner( s.B );
} }
int lineLen = origPathLength(); long long int lineLen = origPathLength();
m_lastLength = lineLen; m_lastLength = lineLen;
m_lastStatus = TUNED; m_lastStatus = TUNED;

View File

@ -89,12 +89,11 @@ public:
bool CheckFit ( MEANDER_SHAPE* aShape ) override; bool CheckFit ( MEANDER_SHAPE* aShape ) override;
protected: protected:
bool doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int aTargetLength );
bool doMove( const VECTOR2I& aP, ITEM* aEndItem, int aTargetLength );
void setWorld( NODE* aWorld ); void setWorld( NODE* aWorld );
virtual int origPathLength() const; virtual long long int origPathLength() const;
///> pointer to world to search colliding items ///> pointer to world to search colliding items
NODE* m_world; NODE* m_world;
@ -113,7 +112,7 @@ protected:
MEANDERED_LINE m_result; MEANDERED_LINE m_result;
SEGMENT* m_initialSegment; SEGMENT* m_initialSegment;
int m_lastLength; long long int m_lastLength;
TUNING_STATUS m_lastStatus; TUNING_STATUS m_lastStatus;
}; };

View File

@ -106,9 +106,9 @@ void MEANDER_PLACER_BASE::cutTunedLine( const SHAPE_LINE_CHAIN& aOrigin,
} }
void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, int aElongation ) void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, long long int aElongation )
{ {
int remaining = aElongation; long long int remaining = aElongation;
bool finished = false; bool finished = false;
for( MEANDER_SHAPE* m : aTuned.Meanders() ) for( MEANDER_SHAPE* m : aTuned.Meanders() )
@ -155,7 +155,7 @@ void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, int aElongatio
} }
} }
int balance = 0; long long int balance = 0;
if( meanderCount ) if( meanderCount )
balance = -remaining / meanderCount; balance = -remaining / meanderCount;
@ -166,7 +166,8 @@ void MEANDER_PLACER_BASE::tuneLineLength( MEANDERED_LINE& aTuned, int aElongatio
{ {
if( m->Type() != MT_CORNER && m->Type() != MT_EMPTY ) if( m->Type() != MT_CORNER && m->Type() != MT_EMPTY )
{ {
m->Resize( std::max( m->Amplitude() - balance / 2, m_settings.m_minAmplitude ) ); m->Resize( std::max( m->Amplitude() - balance / 2,
(long long int) ( m_settings.m_minAmplitude ) ) );
} }
} }
} }
@ -179,7 +180,8 @@ const MEANDER_SETTINGS& MEANDER_PLACER_BASE::MeanderSettings() const
} }
int MEANDER_PLACER_BASE::compareWithTolerance( int aValue, int aExpected, int aTolerance ) const int MEANDER_PLACER_BASE::compareWithTolerance(
long long int aValue, long long int aExpected, long long int aTolerance ) const
{ {
if( aValue < aExpected - aTolerance ) if( aValue < aExpected - aTolerance )
return -1; return -1;

View File

@ -147,14 +147,15 @@ protected:
* Takes a set of meanders in aTuned and tunes their length to * Takes a set of meanders in aTuned and tunes their length to
* extend the original line length by aElongation. * extend the original line length by aElongation.
*/ */
void tuneLineLength( MEANDERED_LINE& aTuned, int aElongation ); void tuneLineLength( MEANDERED_LINE& aTuned, long long int aElongation );
/** /**
* Function compareWithTolerance() * Function compareWithTolerance()
* *
* Compares aValue against aExpected with given tolerance. * Compares aValue against aExpected with given tolerance.
*/ */
int compareWithTolerance ( int aValue, int aExpected, int aTolerance = 0 ) const; int compareWithTolerance(
long long int aValue, long long int aExpected, long long int aTolerance = 0 ) const;
///> width of the meandered trace(s) ///> width of the meandered trace(s)
int m_currentWidth; int m_currentWidth;

View File

@ -99,15 +99,15 @@ bool MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
} }
int MEANDER_SKEW_PLACER::origPathLength( ) const long long int MEANDER_SKEW_PLACER::origPathLength() const
{ {
return itemsetLength ( m_tunedPath ); return itemsetLength ( m_tunedPath );
} }
int MEANDER_SKEW_PLACER::itemsetLength( const ITEM_SET& aSet ) const long long int MEANDER_SKEW_PLACER::itemsetLength( const ITEM_SET& aSet ) const
{ {
int total = 0; long long int total = 0;
for( const ITEM* item : aSet.CItems() ) for( const ITEM* item : aSet.CItems() )
{ {
if( const LINE* l = dyn_cast<const LINE*>( item ) ) if( const LINE* l = dyn_cast<const LINE*>( item ) )
@ -120,7 +120,7 @@ int MEANDER_SKEW_PLACER::itemsetLength( const ITEM_SET& aSet ) const
} }
int MEANDER_SKEW_PLACER::currentSkew() const long long int MEANDER_SKEW_PLACER::currentSkew() const
{ {
return m_lastLength - m_coupledLength; return m_lastLength - m_coupledLength;
} }

View File

@ -52,16 +52,15 @@ public:
const wxString TuningInfo( EDA_UNITS_T aUnits ) const override; const wxString TuningInfo( EDA_UNITS_T aUnits ) const override;
private: private:
long long int currentSkew() const;
long long int itemsetLength( const ITEM_SET& aSet ) const;
int currentSkew( ) const; long long int origPathLength() const override;
int itemsetLength( const ITEM_SET& aSet ) const;
int origPathLength () const override;
DIFF_PAIR m_originPair; DIFF_PAIR m_originPair;
ITEM_SET m_tunedPath, m_tunedPathP, m_tunedPathN; ITEM_SET m_tunedPath, m_tunedPathP, m_tunedPathN;
int m_coupledLength; long long int m_coupledLength;
}; };
} }